Abstract

Trying to collate all plots in a single document, to ease tracking.

Ref: Draft figure overview MetaIBD paper_151121.docx, emails MB-211130 (FW: MetaIBD zoom notes 25-11-21), MB-220307 (Graphing up final gene list), BS-220606 (Paper figure update 2-6-2022).

PCA Plots

Principal Component analysis plots for metatranscriptomics data from the analysis for disease group samples (UC, CD, nonIBD). Computed from the DESeq differential expression analysis on 20200909 on expression features with 100% nucleotide similarity. (20200909-DifferentialExpression).

Activity Level

This PCA plot based on top 500 most variable transcriptomic features, for the 150 time points with Calprotectin activity measured for UC/CD patients. High - Low threshold level set at 200 \(\mu\)g / g.

Disease group

PCA plots using the timepoint data collapsed per sample. Data is in 20200909-DifferentialExpression, and we follow a workflow like in 20191115-DifferentialExpression.

Collapse by sample and filtering of data, all diagnoses.

INFO [2023-03-13 11:24:05] Read DESeq cache file ~/Projects/BIO18025-201808-FunMG-Kaiko/doc/20210907-MaterialsMethodsFigs-MG/mycachefile-participant-data.rds
INFO [2023-03-13 11:24:05] By Sample DESeqDataSet created:
class: DESeqDataSet 
dim: 57081 103 
metadata(1): version
assays(1): counts
rownames(57081): BACT_00007_gene BACT_00012_gene ... BACT_1410510_gene BACT_1410607_gene
rowData names(16): Geneid Chr ... ncbi_type n_taxa
colnames(103): C3001 C3002 ... P6017 P6018
colData names(10): Participant numTPs ... group sex

At 100% protein identity

The dataset contains 57081 CDS features aggregated at the 100% protein (AA) identity level. Non-CDS features have been excluded, and CDS represent about 13% of total transcriptomic reads. Timepoints are collapsed for each sample by median value on each feature, and features which have a minimum of 5 for at least 30% in one diagnosis group are retained.

The following PCA plots are based on the 500 most variable transcriptomic features.

Registered S3 methods overwritten by 'htmltools':
  method               from         
  print.html           tools:rstudio
  print.shiny.tag      tools:rstudio
  print.shiny.tag.list tools:rstudio
Registered S3 method overwritten by 'htmlwidgets':
  method           from         
  print.htmlwidget tools:rstudio

At 98% protein identity

The dataset contains 48752 CDS features aggregated at the 98% protein (AA) identity level. Timepoints are collapsed and CDS features filtered as in the 100% protein identity level dataset. TImepoints are collapsed for each sample by median value on each feature, and features which have a minimum of 5 for at least 30% in one diagnosis group are retained.

The following PCA plots are based on the 500 most variable transcriptomic features.

Feature annotation pie charts

The following plots show the annotation from the prokariotic gene identification pipeline according to the major categories of the Enzyme Commission number (EC numbers) (see here or here) and the Clusters of Orthologous Genes (COGs). For genes with multiple functional annotation in the COG database, the first (main) functional annotation is used.

On all features identified

These give context to the selected lists below. Corresponds to all 1403379 CDS identified from metagenomes, no collapsing by sequence similarity.

On features grouped at 100% protein sequence similarity

The following plots depict annotation proportion on the sequences identified at 100% protein sequence similarity, that also pass the minimum read count filter for differential expression analysis.

On features grouped at 98% sequence similarity

The following plots depict the annotation proportion on the sequences identified at 98% protein sequence similarity, that also pass the minimum read count filter for differential expression analysis.

On common top differentially expressed results from DESeq2 and Variance Partition

The feature type pie charts correspond to the common features from the top 5000 results of each method, at 98% sequence similarity.
The Venn diagrams illustrate the overlap between results at various top results numbers.

INFO [2023-03-13 11:25:16]   CD-nonIBD top 50:   1 common
INFO [2023-03-13 11:25:17]   CD-nonIBD top 500:  16 common
INFO [2023-03-13 11:25:17]   CD-nonIBD top 2000:     163 common
INFO [2023-03-13 11:25:17]   CD-nonIBD top 5000:     752 common

INFO [2023-03-13 11:25:24]   UC-nonIBD top 50:   8 common
INFO [2023-03-13 11:25:24]   UC-nonIBD top 500:  126 common
INFO [2023-03-13 11:25:24]   UC-nonIBD top 2000:     686 common
INFO [2023-03-13 11:25:24]   UC-nonIBD top 5000:     2134 common

INFO [2023-03-13 11:25:29]   High-Low top 50:    0 common
INFO [2023-03-13 11:25:29]   High-Low top 500:   61 common
INFO [2023-03-13 11:25:29]   High-Low top 2000:  339 common
INFO [2023-03-13 11:25:29]   High-Low top 5000:  1177 common

On Top DESeq differential expression results, 98% sequence similarity features

Following plots depict enzyme and COG annotation group on DE results of 98% ss features up to adjusted S-value \(\le\) 10-4, for each contrast.

Protein cluster histograms

|--------------------------------------------------|
|==================================================|

Over all identified genes

Unique genes -> Unique proteins

All unique DNA sequences, expressed or not, clustered at 100% amino acid sequence similarity. Each cluster here is essentially a unique protein.

Unique genes -> Unique portein clusters 98%

All unique DNA sequences (whether expressed or not) clustered at 98% amino acid sequence similarity.

Unique proteins -> Unique protein clusters 98%

Over expressed genes

Histograms and clusters are restricted to those cluster identifiers at 98% that pass the differential expression minimum expression criteria (number of reads in proportion of samples).

Unique genes -> Unique protein clusters 98%

Taxonomic dotplot

INFO [2023-03-13 11:27:55] === Results for diagnosis-CD-nonIBD (100% SS) with LFC > 2 and p-value < 0.0001:
INFO [2023-03-13 11:27:55]   Std: 114
INFO [2023-03-13 11:27:55]   APEglm: 2085
INFO [2023-03-13 11:27:56]   Unique scaffolds: 603
INFO [2023-03-13 11:27:56]   Unique genomes: 90
INFO [2023-03-13 11:27:56]   Unique CDS: 4413; 2085 at 100% SS
INFO [2023-03-13 11:27:56]   Unique taxa Id: 90
INFO [2023-03-13 11:27:56]   Unique species taxa Id: 65
INFO [2023-03-13 11:27:56] The scaffolds picked up by DE genes comprise 387290 / 1434442 (0.27) total genes
INFO [2023-03-13 11:27:57] This is 292386 / 1240722 (0.24) unique AA sequences
INFO [2023-03-13 11:27:58] Restricting to genes that pass expression detection filters, this represents:

   seqid   source       ID prot_uid     cd98 
    2970       90    83672    46482    38963 
INFO [2023-03-13 11:27:58] Where:
                seqid:    scaffold
                source:   NCBI genome
                ID:       Prokka gene
                prot_uid: Unique AA seq (cd100)
                cd98:     Unique cd98 cluster
                

INFO [2023-03-13 11:27:59] === Results for diagnosis-CD-nonIBD (98% SS) with LFC > 2 and p-value < 0.0001:
INFO [2023-03-13 11:27:59]   Std: 159
INFO [2023-03-13 11:27:59]   APEglm: 1590
INFO [2023-03-13 11:28:00]   Unique scaffolds: 700
INFO [2023-03-13 11:28:00]   Unique genomes: 112
INFO [2023-03-13 11:28:00]   Unique CDS: 6352; 1590 at 98% SS
INFO [2023-03-13 11:28:00]   Unique taxa Id: 112
INFO [2023-03-13 11:28:00]   Unique species taxa Id: 81
INFO [2023-03-13 11:28:00] The scaffolds picked up by DE genes comprise 462279 / 1434442 (0.32) total genes
INFO [2023-03-13 11:28:01] This is 357349 / 1240722 (0.29) unique AA sequences
INFO [2023-03-13 11:28:01] Restricting to genes that pass expression detection filters, this represents:

   seqid   source       ID prot_uid     cd98 
    3564      112   115515    73163    42528 
INFO [2023-03-13 11:28:01] Where:
                seqid:    scaffold
                source:   NCBI genome
                ID:       Prokka gene
                prot_uid: Unique AA seq (cd100)
                cd98:     Unique cd98 cluster
                

INFO [2023-03-13 11:28:03] === Results for diagnosis-UC-nonIBD (100% SS) with LFC > 2 and p-value < 0.0001:
INFO [2023-03-13 11:28:03]   Std: 42
INFO [2023-03-13 11:28:03]   APEglm: 622
INFO [2023-03-13 11:28:04]   Unique scaffolds: 302
INFO [2023-03-13 11:28:04]   Unique genomes: 110
INFO [2023-03-13 11:28:04]   Unique CDS: 895; 622 at 100% SS
INFO [2023-03-13 11:28:04]   Unique taxa Id: 110
INFO [2023-03-13 11:28:04]   Unique species taxa Id: 92
INFO [2023-03-13 11:28:04] The scaffolds picked up by DE genes comprise 436161 / 1434442 (0.30) total genes
INFO [2023-03-13 11:28:05] This is 351270 / 1240722 (0.28) unique AA sequences
INFO [2023-03-13 11:28:05] Restricting to genes that pass expression detection filters, this represents:

   seqid   source       ID prot_uid     cd98 
    3502      110    89779    53799    45728 
INFO [2023-03-13 11:28:05] Where:
                seqid:    scaffold
                source:   NCBI genome
                ID:       Prokka gene
                prot_uid: Unique AA seq (cd100)
                cd98:     Unique cd98 cluster
                

INFO [2023-03-13 11:28:06] === Results for diagnosis-UC-nonIBD (98% SS) with LFC > 2 and p-value < 0.0001:
INFO [2023-03-13 11:28:06]   Std: 49
INFO [2023-03-13 11:28:06]   APEglm: 628
INFO [2023-03-13 11:28:07]   Unique scaffolds: 425
INFO [2023-03-13 11:28:07]   Unique genomes: 128
INFO [2023-03-13 11:28:07]   Unique CDS: 1364; 628 at 98% SS
INFO [2023-03-13 11:28:07]   Unique taxa Id: 128
INFO [2023-03-13 11:28:07]   Unique species taxa Id: 108
INFO [2023-03-13 11:28:08] The scaffolds picked up by DE genes comprise 498416 / 1434442 (0.35) total genes
INFO [2023-03-13 11:28:09] This is 404081 / 1240722 (0.33) unique AA sequences
INFO [2023-03-13 11:28:09] Restricting to genes that pass expression detection filters, this represents:

   seqid   source       ID prot_uid     cd98 
    3956      128   118386    78048    48523 
INFO [2023-03-13 11:28:09] Where:
                seqid:    scaffold
                source:   NCBI genome
                ID:       Prokka gene
                prot_uid: Unique AA seq (cd100)
                cd98:     Unique cd98 cluster
                

INFO [2023-03-13 11:28:11] === Results for ActivityLevel-High-Low (100% SS) with LFC > 2 and p-value < 0.0001:
INFO [2023-03-13 11:28:11]   Std: 0
INFO [2023-03-13 11:28:11]   APEglm: 271
INFO [2023-03-13 11:28:12]   Unique scaffolds: 210
INFO [2023-03-13 11:28:12]   Unique genomes: 60
INFO [2023-03-13 11:28:12]   Unique CDS: 544; 271 at 100% SS
INFO [2023-03-13 11:28:12]   Unique taxa Id: 60
INFO [2023-03-13 11:28:12]   Unique species taxa Id: 41
INFO [2023-03-13 11:28:12] The scaffolds picked up by DE genes comprise 280764 / 1434442 (0.20) total genes
INFO [2023-03-13 11:28:13] This is 214221 / 1240722 (0.17) unique AA sequences
INFO [2023-03-13 11:28:13] Restricting to genes that pass expression detection filters, this represents:

   seqid   source       ID prot_uid     cd98 
    2432       60    63246    35435    28901 
INFO [2023-03-13 11:28:13] Where:
                seqid:    scaffold
                source:   NCBI genome
                ID:       Prokka gene
                prot_uid: Unique AA seq (cd100)
                cd98:     Unique cd98 cluster
                

INFO [2023-03-13 11:28:14] === Results for ActivityLevel-High-Low (98% SS) with LFC > 2 and p-value < 0.0001:
INFO [2023-03-13 11:28:14]   Std: 0
INFO [2023-03-13 11:28:14]   APEglm: 225
INFO [2023-03-13 11:28:15]   Unique scaffolds: 273
INFO [2023-03-13 11:28:15]   Unique genomes: 65
INFO [2023-03-13 11:28:15]   Unique CDS: 661; 225 at 98% SS
INFO [2023-03-13 11:28:15]   Unique taxa Id: 65
INFO [2023-03-13 11:28:15]   Unique species taxa Id: 44
INFO [2023-03-13 11:28:15] The scaffolds picked up by DE genes comprise 310698 / 1434442 (0.22) total genes
INFO [2023-03-13 11:28:16] This is 232545 / 1240722 (0.19) unique AA sequences
INFO [2023-03-13 11:28:16] Restricting to genes that pass expression detection filters, this represents:

   seqid   source       ID prot_uid     cd98 
    2828       65    91813    56112    29976 
INFO [2023-03-13 11:28:16] Where:
                seqid:    scaffold
                source:   NCBI genome
                ID:       Prokka gene
                prot_uid: Unique AA seq (cd100)
                cd98:     Unique cd98 cluster
                
INFO [2023-03-13 11:28:17] Accross all 3 DE contrasts (CD - nonIBD, UC - nonIBD, Activity High - Low) and 2 clustering strategies (100%, 98%) we have in total:
INFO [2023-03-13 11:28:17]     431 taxa (134 unique), distributed as:
INFO [2023-03-13 11:28:17] 


Act. High - Low (100% SS)  Act. High - Low (98% SS)     CD - nonIBD (100% SS)      CD - nonIBD (98% SS)     UC - nonIBD (100% SS) 
                       41                        44                        65                        81                        92 
     UC - nonIBD (98% SS) 
                      108 
INFO [2023-03-13 11:28:17]     14229 individual gene results (9017 unique)

LS0tCnRpdGxlOiAiQWxsIFBsb3RzIgpkYXRlOiAiYHIgU3lzLkRhdGUoKWAiCmF1dGhvcjoKLSBuYW1lOiBcYmdyb3VwIEhNUkkgQmlvaW5mb3JtYXRpY3NcbmV3bGluZSBDYXJsb3MgUml2ZXJvc1xlZ3JvdXAKICBlbWFpbDogY2FybG9zLnJpdmVyb3NAaG1yaS5vcmcuYXUKb3V0cHV0OiAKICBodG1sX25vdGVib29rOiAKICAgIHRvYzogeWVzCiAgICB0b2NfZmxvYXQ6IHRydWUKICAgIHRvY19jb2xsYXBzZWQ6IHRydWUKICAgIGhpZ2hsaWdodDogdGFuZ28KICAgIHRoZW1lOiBzcGFjZWxhYgogICAgY29kZV9mb2xkaW5nOiBoaWRlCiAgICBmaWdfd2lkdGg6IDgKICAgIGZpZ19oZWlnaHQ6IDYKICAgIGZpZ19jYXB0aW9uOiB5ZXMKLS0tCgpgYGB7ciBpbmNsdWRlID0gRkFMU0V9CmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvPUZBTFNFKQoKbGlicmFyeShkYXRhLnRhYmxlKQpsaWJyYXJ5KG9wZW54bHN4KQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoREVTZXEyKQpsaWJyYXJ5KGZ1dGlsZS5sb2dnZXIpCmxpYnJhcnkobWFncml0dHIpCmBgYAoKIyBBYnN0cmFjdAoKVHJ5aW5nIHRvIGNvbGxhdGUgYWxsIHBsb3RzIGluIGEgc2luZ2xlIGRvY3VtZW50LCB0byBlYXNlIHRyYWNraW5nLgoKUmVmOiBbRHJhZnQgZmlndXJlIG92ZXJ2aWV3IE1ldGFJQkQgcGFwZXJfMTUxMTIxLmRvY3hdKCksIGVtYWlscyBNQi0yMTExMzAgKEZXOiBNZXRhSUJEIHpvb20gbm90ZXMgMjUtMTEtMjEpLCBNQi0yMjAzMDcgKEdyYXBoaW5nIHVwIGZpbmFsIGdlbmUgbGlzdCksIEJTLTIyMDYwNiAoUGFwZXIgZmlndXJlIHVwZGF0ZSAyLTYtMjAyMikuCgpgYGB7ciwgZWNobz1GQUxTRX0KcHJvakRpciA9ICd+L1Byb2plY3RzL0JJTzE4MDI1LTIwMTgwOC1GdW5NRy1LYWlrby8nCm91dDJEaXIgPSBwYXN0ZTAocHJvakRpciwgJ2RvYy8yMDIxMDkwNy1NYXRlcmlhbHNNZXRob2RzRmlncy1NRy8nKQpvdXREaXIgPSBwYXN0ZTAocHJvakRpciwgJ2RvYy8yMDIzMDMwMS1QbG90cy1NTS1GdW5NRy8nKQptZXRhRGlyICA9IHBhc3RlMChwcm9qRGlyLCAnZGF0YS8yMDE5MDUwMS1NZXRhZGF0YS8nKQoKbWluLnJlYWRzID0gNQptaW4uc2FtcF9wcm9wID0gMC4zCnRocmVzLnB2ID0gMWUtNAp0aHJlcy5sZmMgPSAyCmBgYAoKIyBQQ0EgUGxvdHMKClByaW5jaXBhbCBDb21wb25lbnQgYW5hbHlzaXMgcGxvdHMgZm9yIG1ldGF0cmFuc2NyaXB0b21pY3MgZGF0YSBmcm9tIHRoZSBhbmFseXNpcyBmb3IgZGlzZWFzZSBncm91cCBzYW1wbGVzIChVQywgQ0QsIG5vbklCRCkuCkNvbXB1dGVkIGZyb20gdGhlIERFU2VxIGRpZmZlcmVudGlhbCBleHByZXNzaW9uIGFuYWx5c2lzIG9uIDIwMjAwOTA5IG9uIGV4cHJlc3Npb24gZmVhdHVyZXMgd2l0aCAxMDAlIG51Y2xlb3RpZGUgc2ltaWxhcml0eS4KKGAyMDIwMDkwOS1EaWZmZXJlbnRpYWxFeHByZXNzaW9uYCkuCgojIyMgQWN0aXZpdHkgTGV2ZWwKCmBgYHtyfQojIFVzaW5nIGNhY2hlZCBkYXRhIGZyb20gREV4cCBhbmFseXNpcy4KZGV4cERpcjAgPSBwYXN0ZTAocHJvakRpciwgJ2RvYy8yMDIwMDkwOS1EaWZmZXJlbnRpYWxFeHByZXNzaW9uLycpCiMgRm9yIHZhcmlhbmNlIHBhcnRpdGlvbiByZXN1bHRzCmRleHBEaXIxID0gcGFzdGUwKHByb2pEaXIsICdkb2MvMjAyMTExMjktRGlmZmVyZW50aWFsRXhwcmVzc2lvbi1EaWFnbm9zaXMvJykKZGV4cERpcjIgPSBwYXN0ZTAocHJvakRpciwgJ2RvYy8yMDIyMDIwOS1EaWZmZXJlbnRpYWxFeHByZXNzaW9uLUFjdGl2aXR5LycpCgpjYWNoZUZpbGVWYXIgPSBwYXN0ZTAoZGV4cERpcjAsICdteWNhY2hlZmlsZS1BY3Rpdml0eUxldmVsLkhpZ2guTG93LXZhcjEuUkRhdGEnKQoKc3RvcGlmbm90KGRpci5leGlzdHMocGF0aC5leHBhbmQoZGV4cERpcjApKSAmJiBmaWxlLmV4aXN0cyhjYWNoZUZpbGVWYXIpKQoKewogIGJiID0gbmV3LmVudigpCiAgbG9hZChmaWxlPWNhY2hlRmlsZVZhciwgZW52aXI9YmIpCiAgc3RvcGlmbm90KGFsbChjKCdybGQnLCd2c3QnLCdudHInKSAlaW4lIG5hbWVzKGJiKSkpCiAgZm9yKHZuIGluIGMoJ3JsZCcsJ3ZzdCcsJ250cicpKSB7CiAgICBpZighaXMubnVsbChnZXQodm4sIGVudmlyPWJiKSkpIHsKICAgICAgYXNzaWduKHBhc3RlMCgnYWN0SEwuJywgdm4pLCBnZXQodm4sIGVudmlyPWJiKSkKICAgIH0KICB9CiAgcm0oYmIpCn0KYGBgCgpgYGB7ciwgZmlnLmhlaWdodD02LCBmaWcud2lkdGg9OH0KZDEgPSBwbG90UENBKG9iamVjdD1hY3RITC52c3QsIGludGdyb3VwPSdBY3Rpdml0eUxldmVsJywgcmV0dXJuRGF0YT1GKSArCiAgICAgdGhlbWVfbGluZWRyYXcoKSArIAogICAgIGxhYnModGl0bGU9J1RpbWUgcG9pbnRzIFBDQSwgQWN0aXZpdHkgTGV2ZWwnLCBzdWJ0aXRsZT1wYXN0ZTAobmNvbChhY3RITC52c3QpLCAnIHRpbWUgcG9pbnRzJykpCnBsb3QoZDEpCmBgYAoKVGhpcyBQQ0EgcGxvdCBiYXNlZCBvbiB0b3AgNTAwIG1vc3QgdmFyaWFibGUgdHJhbnNjcmlwdG9taWMgZmVhdHVyZXMsIGZvciB0aGUgYHIgbmNvbChhY3RITC52c3QpYCB0aW1lIHBvaW50cyB3aXRoIENhbHByb3RlY3RpbiBhY3Rpdml0eSBtZWFzdXJlZCBmb3IgVUMvQ0QgcGF0aWVudHMuCkhpZ2ggLSBMb3cgdGhyZXNob2xkIGxldmVsIHNldCBhdCAyMDAgJFxtdSRnIC8gZy4KCgojIyMgRGlzZWFzZSBncm91cAoKUENBIHBsb3RzIHVzaW5nIHRoZSB0aW1lcG9pbnQgZGF0YSBjb2xsYXBzZWQgcGVyIHNhbXBsZS4gIERhdGEgaXMgaW4gYDIwMjAwOTA5LURpZmZlcmVudGlhbEV4cHJlc3Npb25gLCBhbmQgd2UgZm9sbG93IGEgd29ya2Zsb3cgbGlrZSBpbiBgMjAxOTExMTUtRGlmZmVyZW50aWFsRXhwcmVzc2lvbmAuCgpDb2xsYXBzZSBieSBzYW1wbGUgYW5kIGZpbHRlcmluZyBvZiBkYXRhLCBhbGwgZGlhZ25vc2VzLgpgYGB7cn0KbWluLnJlYWRzID0gNQptaW4uc2FtcF9wcm9wID0gMC4zCgpjYWNoZUZpbGUgPSBwYXN0ZTAob3V0MkRpciwgJ215Y2FjaGVmaWxlLXBhcnRpY2lwYW50LWRhdGEucmRzJykKaWYoIWZpbGUuZXhpc3RzKGNhY2hlRmlsZSkpewogIAogIGRhdGFEaXIgPSBwYXN0ZTAocHJvakRpciwgJ2RhdGEvMjAyMDA5MDktQ291bnRzT1JGLycpCiAgY291bnRGaWxlQ2FjaGUgPSBwYXN0ZTAoZGF0YURpciwgJ2NvdW50cy1PUkYtMTAwLWZyYWMucmRzJykKICBzdG9waWZub3QoZmlsZS5leGlzdHMoY291bnRGaWxlQ2FjaGUpKQogIAogIGNvdW50SW5mbyA9IHJlYWRSRFMoZmlsZT1jb3VudEZpbGVDYWNoZSkKICBmbG9nLmluZm8oJ1JlYWQgY2FjaGUgZmlsZSAlcycsIGNvdW50RmlsZUNhY2hlKQogIAogIGZsb2cuaW5mbygnRGltZW5zaW9uIG9mIHRyYW5zY3JpcHRpb24gbWF0cml4ICVkIHggJWQgKHRyYW5zYyB4IHRpbWVwb2ludHMpOicsIG5yb3coY291bnRJbmZvJGNvdW50cyksIG5jb2woY291bnRJbmZvJGNvdW50cykpCiAgZmxvZy5pbmZvKCdOdW1iZXIgb2YgdW5pcXVlIHRyYW5zY3JpcHRzIHBhc3NpbmcgaW5pdGlhbCBmaWx0ZXJzOiAlZCcsIGxlbmd0aChjb3VudEluZm8kbm9ubmVnbGlnKSkKICAKICBzYW1wc0ZpbGVDYWNoZSA9IHBhc3RlMChkYXRhRGlyLCAnZnVubWctc2FtcGxlcy5yZHMnKSAgIyBPcmlnaW5hbGx5IGluIDIwMTkxMDExLURpc2Vhc2VBY3Rpdml0eQogIHN0b3BpZm5vdChmaWxlLmV4aXN0cyhzYW1wc0ZpbGVDYWNoZSkpCiAgCiAgc2FtcGxlSW5mbyA9IHJlYWRSRFMoZmlsZT1zYW1wc0ZpbGVDYWNoZSkKICBmbG9nLmluZm8oJ1JlYWQgc2FtcGxlIGZpbGUgY2FjaGU6ICVzJywgc2FtcHNGaWxlQ2FjaGUpCiAgCiAgZmxvZy5pbmZvKCdHcm91cCBpZGVudGlmaWNhdGlvbiBmb3IgJWQgdGltZXBvaW50cycsIG5yb3coc2FtcGxlSW5mbykpCiAgCiAgCiAgbm4gPSBtYXRjaChzYW1wbGVJbmZvWywgcGFzdGUwKHBlcnNvbiwnLicsdHApXSwgY29sbmFtZXMoY291bnRJbmZvJGNvdW50cykpCiAgc3RvcGlmbm90KGFsbC5lcXVhbChjb2xuYW1lcyhjb3VudEluZm8kY291bnRzKVtubl0sIHNhbXBsZUluZm9bLCBwYXN0ZTAocGVyc29uLCcuJyx0cCldKSkKICBkcyA9IGNvdW50SW5mbyRjb3VudHNbLCAuLm5uXQogIHJvd0QgPSBjb3VudEluZm8kY291bnRzWywgLihHZW5laWQsIENociwgU3RhcnQsIEVuZCwgU3RyYW5kLCBMZW5ndGgsIG9yaWdfaWQsIG51Y191aWQsIHByb3RfdWlkLCBjZDk4LCBjZDk1LCBuYW1lLCBsZW4sIHBya190eXBlLCBuY2JpX3R5cGUpXQogIAogIHJtKGNvdW50SW5mbykKICBnYyhmdWxsID0gVCkKICAKICBkczIgPSBkYXRhLnRhYmxlKCkKICBmb3Ioc3MgaW4gdW5pcXVlKHNhbXBsZUluZm8kUGFydGljaXBhbnQpKSB7CiAgICBubiA9IGdyZXAocGF0dGVybj1wYXN0ZTAoJ14nLHNzKSwgeD1jb2xuYW1lcyhkcykpCiAgICAjIHNldChkczIsIGo9c3MsIHZhbHVlPWRzWywgcm93TWVhbnMoLlNEKSwgLlNEY29scz1ubl0gLyBsZW5ndGgobm4pKQogICAgc2V0KGRzMiwgaj1zcywgdmFsdWU9cm91bmQocm93TWVkaWFucyhhcy5tYXRyaXgoZHNbLCAuU0QsIC5TRGNvbHM9bm5dKSwgbmEucm09VCkpKQogIH0KICAKICBybShkcykKICBnYyhmdWxsID0gVCkKCiAgbHMyID0gTWF0cml4OjpNYXRyaXgoYXMubWF0cml4KGRzMikgPiBtaW4ucmVhZHMpCiAgCiAgenogPSByZXAoRiwgbnJvdyhsczIpKQogIGZvcihrIGluIHVuaXF1ZShzYW1wbGVJbmZvJGRpYWdub3NpcykpIHsKICAgIG5uID0gd2hpY2goY29sbmFtZXMobHMyKSAlaW4lIHVuaXF1ZShzYW1wbGVJbmZvW2RpYWdub3NpcyA9PSBrLCBQYXJ0aWNpcGFudF0pKQogICAgenogPSB6eiB8IChNYXRyaXg6OnJvd1N1bXMobHMyWywgbm5dKSAvIGxlbmd0aChubikgPiBtaW4uc2FtcF9wcm9wKQogIH0KICAKICBybShsczIpCiAgZ2MoZnVsbCA9IFQpCiAgCiAgYnlQYXJ0U0kgPSBzYW1wbGVJbmZvWywgLihudW1UUHM9Lk4sIG1lYW5JbnRlcnZhbD1tZWFuKGludGVydmFsX2RheXMsbmEucm09VCksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgQWdlLmF0LmRpYWdub3Npcz1taW4oQWdlLmF0LmRpYWdub3NpcyksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBEaWFnbm9zaXM9dW5pcXVlKGRpYWdub3NpcylbMV0sIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgT2NjdXBhdGlvbj11bmlxdWUoT2NjdXBhdGlvbilbMV0sIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgRWR1Y2F0aW9uPXVuaXF1ZShFZHVjYXRpb24pWzFdLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZlY2FsY2FsPW1lYW4oZmVjYWxjYWwsIG5hLnJtPVQpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3JvdXA9dW5pcXVlKGdyb3VwKVsxXSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNleD11bmlxdWUoc2V4KVsxXSksCiAgICAgICAgICAgICAgICAgICAgICAgIGJ5PVBhcnRpY2lwYW50XQogICMgRW5zdXJlIHNhbWUgb3JkZXIgYXMgZGF0YQogIGJ5UGFydFNJID0gYnlQYXJ0U0lbbWF0Y2goYnlQYXJ0U0kkUGFydGljaXBhbnQsIGNvbG5hbWVzKGRzMikpLCBdCiAgcm93bmFtZXMoYnlQYXJ0U0kpID0gY29sbmFtZXMoZHMyKQogIAogIGRkcyA8LSBERVNlcURhdGFTZXRGcm9tTWF0cml4KGNvdW50RGF0YT1kczJbenosXSwgY29sRGF0YT1ieVBhcnRTSSwgZGVzaWduPSB+IGdyb3VwLCByb3dEYXRhPXJvd0RbenosIF0pCiAgcm93bmFtZXMoZGRzKSA9IHJvd0QkR2VuZWlkW3p6XQogIAogIGNhY2hlRmlsZSA9IHBhc3RlMChvdXREaXIsICAnbXljYWNoZWZpbGUtcGFydGljaXBhbnQtZGF0YS5yZHMnKQogIHNhdmVSRFMoZGRzLCBmaWxlPWNhY2hlRmlsZSkKICBmbG9nLmluZm8oJ1dyb3RlIERFU2VxIGNhY2hlIGZpbGUgJXMnLCBjYWNoZUZpbGUpCn0gZWxzZSB7CiAgZGRzID0gcmVhZFJEUyhjYWNoZUZpbGUpCiAgZmxvZy5pbmZvKCdSZWFkIERFU2VxIGNhY2hlIGZpbGUgJXMnLCBjYWNoZUZpbGUpCn0KZmxvZy5pbmZvKCdCeSBTYW1wbGUgREVTZXFEYXRhU2V0IGNyZWF0ZWQ6JykKZGRzCmBgYAojIyMjIEF0IDEwMCUgcHJvdGVpbiBpZGVudGl0eQoKYGBge3J9CmNhY2hlRmlsZVZhciA9IHBhc3RlMChvdXQyRGlyLCAnbXljYWNoZWZpbGUtcGFydGljaXBhbnQtdmFyMS5SRGF0YScpCmlmKCFmaWxlLmV4aXN0cyhjYWNoZUZpbGVWYXIpKSB7CgogIHZzdCA9IG50ciA9IE5VTEwKICAjIFdlIGRvIGluIHRoaXMgb3JkZXIgdG8gYXZvaWQgcHJvYmxlbXMgd2l0aCBnZW9tZXRyaWMgbWVhbiB3aGVuIGFsbCAvIG1vc3QgZ2VuZXMgaGF2ZSBhdCBsZWFzdCBvbmUgemVybyB2YWx1ZQogIGFiID0gZXN0aW1hdGVTaXplRmFjdG9yc0Zvck1hdHJpeChjb3VudHM9Y291bnRzKGRkcykrMSwgbG9jZnVuYz1nZW5lZmlsdGVyOjpzaG9ydGgpCiAgc2l6ZUZhY3RvcnMoZGRzKSA9IGFiCiAgbnRyID0gbm9ybVRyYW5zZm9ybShkZHMpCiAgZmxvZy5pbmZvKCdDb21wdXRlZCBub3JtYWwgdHJhbnNmb3JtIHZhcmlhbmNlIHN0YWJpbGlzYXRpb24nKQogIHZzdCA9IHZhcmlhbmNlU3RhYmlsaXppbmdUcmFuc2Zvcm1hdGlvbihkZHMsIGJsaW5kPVQpCiAgZmxvZy5pbmZvKCdDb21wdXRlZCBWU1QgdmFyaWFuY2Ugc3RhYmlsaXNhdGlvbicpCgogIGNhY2hlRmlsZVZhciA9IHBhc3RlMChvdXREaXIsICdteWNhY2hlZmlsZS1wYXJ0aWNpcGFudC12YXIxLlJEYXRhJykKICBzYXZlKG50ciwgdnN0LCBmaWxlPWNhY2hlRmlsZVZhcikKICBmbG9nLmluZm8oJ1dyb3RlIGNhY2hlICVzJywgY2FjaGVGaWxlVmFyKQogIGRub3ZvMTAwLm50ciA9IG50cgogIGRub3ZvMTAwLnZzdCA9IHZzdAp9IGVsc2UgewogIGJiID0gbmV3LmVudigpCiAgbG9hZChmaWxlPWNhY2hlRmlsZVZhciwgZW52aXI9YmIpCiAgc3RvcGlmbm90KGFsbChjKCd2c3QnLCdudHInKSAlaW4lIG5hbWVzKGJiKSkpCiAgZm9yKHZuIGluIGMoJ3ZzdCcsJ250cicpKSB7CiAgICBpZighaXMubnVsbChnZXQodm4sIGVudmlyPWJiKSkpIHsKICAgICAgYXNzaWduKHBhc3RlMCgnZG5vdm8xMDAuJywgdm4pLCBnZXQodm4sIGVudmlyPWJiKSkKICAgIH0KICB9CiAgcm0oYmIpCn0KYGBgCgpUaGUgZGF0YXNldCBjb250YWlucyBgciBucm93KGRub3ZvMTAwLnZzdClgIENEUyBmZWF0dXJlcyBhZ2dyZWdhdGVkIGF0IHRoZSAxMDAlIHByb3RlaW4gKEFBKSBpZGVudGl0eSBsZXZlbC4KTm9uLUNEUyBmZWF0dXJlcyBoYXZlIGJlZW4gZXhjbHVkZWQsIGFuZCBDRFMgcmVwcmVzZW50IGFib3V0IDEzJSBvZiB0b3RhbCB0cmFuc2NyaXB0b21pYyByZWFkcy4KVGltZXBvaW50cyBhcmUgY29sbGFwc2VkIGZvciBlYWNoIHNhbXBsZSBieSBtZWRpYW4gdmFsdWUgb24gZWFjaCBmZWF0dXJlLCBhbmQgZmVhdHVyZXMgd2hpY2ggaGF2ZSBhIG1pbmltdW0gb2YgYHIgbWluLnJlYWRzYCAKZm9yIGF0IGxlYXN0IGByIG1pbi5zYW1wX3Byb3AqMTAwYCUgIGluIG9uZSBkaWFnbm9zaXMgZ3JvdXAgYXJlIHJldGFpbmVkLgoKVGhlIGZvbGxvd2luZyBQQ0EgcGxvdHMgYXJlIGJhc2VkIG9uIHRoZSA1MDAgbW9zdCB2YXJpYWJsZSB0cmFuc2NyaXB0b21pYyBmZWF0dXJlcy4KCmBgYHtyLCBmaWcuaGVpZ2h0PTYsIGZpZy53aWR0aD04LCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpkMiA9IHBsb3RQQ0Eob2JqZWN0PWRub3ZvMTAwLnZzdCwgaW50Z3JvdXA9J0RpYWdub3NpcycsIHJldHVybkRhdGE9RikgKwogICAgIHRoZW1lX2xpbmVkcmF3KCkgKyAKICAgICBsYWJzKHRpdGxlPSdQYXRpZW50IGRpYWdub3NpcyBvbiBQQ0EnLCBzdWJ0aXRsZT1wYXN0ZTAobmNvbChkbm92bzEwMC52c3QpLCAnIHBhdGllbnRzLiAxMDAlIEFBIHNpbWlsYXJpdHknKSkKcGxvdChkMikKYGBgCgoKYGBge3IsIGZpZy5oZWlnaHQ9NiwgZmlnLndpZHRoPTh9CmQyID0gcGxvdFBDQShvYmplY3Q9ZG5vdm8xMDAudnN0LCBpbnRncm91cD0nc2V4JywgcmV0dXJuRGF0YT1GKSArCiAgICAgdGhlbWVfbGluZWRyYXcoKSArIAogICAgIGxhYnModGl0bGU9J1BhdGllbnQgZ2VuZGVyIG9uIFBDQScsIHN1YnRpdGxlPXBhc3RlMChuY29sKGRub3ZvMTAwLnZzdCksICcgcGF0aWVudHMuIDEwMCUgQUEgc2ltaWxhcml0eScpKQpwbG90KGQyKQpgYGAKCmBgYHtyLCBmaWcuaGVpZ2h0PTYsIGZpZy53aWR0aD04LCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQpkMiA9IHBsb3RQQ0Eob2JqZWN0PWRub3ZvMTAwLnZzdCwgaW50Z3JvdXA9J0FnZS5hdC5kaWFnbm9zaXMnLCByZXR1cm5EYXRhPUYpICsKICAgICB0aGVtZV9saW5lZHJhdygpICsgCiAgICAgbGFicyh0aXRsZT0nUGF0aWVudCBhZ2Ugb24gUENBJywgc3VidGl0bGU9cGFzdGUwKG5jb2woZG5vdm8xMDAudnN0KSwgJyBwYXRpZW50cy4gMTAwJSBBQSBzaW1pbGFyaXR5JykpICsKICAgICBzY2FsZV9jb2xvcl92aXJpZGlzX2Mob3B0aW9uID0gJ3BsYXNtYScpCnBsb3QoZDIpCmBgYAoKIyMjIyBBdCA5OCUgcHJvdGVpbiBpZGVudGl0eQoKYGBge3J9CmNhY2hlRmlsZVZhciA9IHBhc3RlMChvdXQyRGlyLCAnbXljYWNoZWZpbGUtcGFydGljaXBhbnQtdmFyMi5SRGF0YScpCmlmKCFmaWxlLmV4aXN0cyhjYWNoZUZpbGVWYXIpKSB7CgogIGRzID0gY291bnRzKGRkcykKICByRCA9IGFzLmRhdGEudGFibGUocm93RGF0YShkZHMpKQogIGRzMiA9IE5VTEwKICByRDIgPSBOVUxMCiAgZm9yKHNzIGluIHVuaXF1ZShyRCRjZDk4KSkgewogICAgbm4gPSByRFtjZDk4ID09IHNzLCB3aGljaCA9IFRdCiAgICBpZihsZW5ndGgobm4pID4gMSkgewogICAgICBkczIgPSByYmluZChkczIsIGNvbFN1bXMoZHNbbm4sIF0pKQogICAgICByRDIgPSByYmluZChyRDIsIHJEW25uWzFdLCBdKQogICAgICByRDIkbl90YXhhID0gc3VtKHJEJG5fdGF4YVtubl0pCiAgICB9IGVsc2UgewogICAgICBkczIgPSByYmluZChkczIsIGRzW25uLCBdKQogICAgICByRDIgPSByYmluZChyRDIsIHJEW25uLCBdKQogICAgfQogIH0KICByb3duYW1lcyhyRDIpID0gckQyJEdlbmVpZCA9IHJEMiRjZDk4CgogIGRkcyA8LSBERVNlcURhdGFTZXRGcm9tTWF0cml4KGNvdW50RGF0YT1kczIsIGNvbERhdGE9Y29sRGF0YShkZHMpLCBkZXNpZ249IH4gZ3JvdXAsIHJvd0RhdGE9ckQyKQogIHJvd25hbWVzKGRkcykgPSByb3dEJEdlbmVpZFt6el0KCiAgdnN0ID0gbnRyID0gTlVMTAogICMgV2UgZG8gaW4gdGhpcyBvcmRlciB0byBhdm9pZCBwcm9ibGVtcyB3aXRoIGdlb21ldHJpYyBtZWFuIHdoZW4gYWxsIC8gbW9zdCBnZW5lcyBoYXZlIGF0IGxlYXN0IG9uZSB6ZXJvIHZhbHVlCiAgYWIgPSBlc3RpbWF0ZVNpemVGYWN0b3JzRm9yTWF0cml4KGNvdW50cz1jb3VudHMoZGRzKSsxLCBsb2NmdW5jPWdlbmVmaWx0ZXI6OnNob3J0aCkKICBzaXplRmFjdG9ycyhkZHMpID0gYWIKICBudHIgPSBub3JtVHJhbnNmb3JtKGRkcykKICBmbG9nLmluZm8oJ0NvbXB1dGVkIG5vcm1hbCB0cmFuc2Zvcm0gdmFyaWFuY2Ugc3RhYmlsaXNhdGlvbicpCiAgdnN0ID0gdmFyaWFuY2VTdGFiaWxpemluZ1RyYW5zZm9ybWF0aW9uKGRkcywgYmxpbmQ9VCkKICBmbG9nLmluZm8oJ0NvbXB1dGVkIFZTVCB2YXJpYW5jZSBzdGFiaWxpc2F0aW9uJykKCiAgY2FjaGVGaWxlVmFyID0gcGFzdGUwKG91dERpciwgJ215Y2FjaGVmaWxlLXBhcnRpY2lwYW50LXZhcjIuUkRhdGEnKQogIHNhdmUobnRyLCB2c3QsIGZpbGU9Y2FjaGVGaWxlVmFyKQogIGZsb2cuaW5mbygnV3JvdGUgY2FjaGUgJXMnLCBjYWNoZUZpbGVWYXIpCiAgZG5vdm85OC5udHIgPSBudHIKICBkbm92bzk4LnZzdCA9IHZzdAp9IGVsc2UgewogIGJiID0gbmV3LmVudigpCiAgbG9hZChmaWxlPWNhY2hlRmlsZVZhciwgZW52aXI9YmIpCiAgc3RvcGlmbm90KGFsbChjKCd2c3QnLCdudHInKSAlaW4lIG5hbWVzKGJiKSkpCiAgZm9yKHZuIGluIGMoJ3ZzdCcsJ250cicpKSB7CiAgICBpZighaXMubnVsbChnZXQodm4sIGVudmlyPWJiKSkpIHsKICAgICAgYXNzaWduKHBhc3RlMCgnZG5vdm85OC4nLCB2biksIGdldCh2biwgZW52aXI9YmIpKQogICAgfQogIH0KICBybShiYikKfQpgYGAKClRoZSBkYXRhc2V0IGNvbnRhaW5zIGByIG5yb3coZG5vdm85OC52c3QpYCBDRFMgZmVhdHVyZXMgYWdncmVnYXRlZCBhdCB0aGUgOTglIHByb3RlaW4gKEFBKSBpZGVudGl0eSBsZXZlbC4KVGltZXBvaW50cyBhcmUgY29sbGFwc2VkIGFuZCBDRFMgZmVhdHVyZXMgZmlsdGVyZWQgYXMgaW4gdGhlIDEwMCUgcHJvdGVpbiBpZGVudGl0eSBsZXZlbCBkYXRhc2V0LgpUSW1lcG9pbnRzIGFyZSBjb2xsYXBzZWQgZm9yIGVhY2ggc2FtcGxlIGJ5IG1lZGlhbiB2YWx1ZSBvbiBlYWNoIGZlYXR1cmUsIGFuZCBmZWF0dXJlcyB3aGljaCBoYXZlIGEgbWluaW11bSBvZiBgciBtaW4ucmVhZHNgIApmb3IgYXQgbGVhc3QgYHIgbWluLnNhbXBfcHJvcCoxMDBgJSAgaW4gb25lIGRpYWdub3NpcyBncm91cCBhcmUgcmV0YWluZWQuCgpUaGUgZm9sbG93aW5nIFBDQSBwbG90cyBhcmUgYmFzZWQgb24gdGhlIDUwMCBtb3N0IHZhcmlhYmxlIHRyYW5zY3JpcHRvbWljIGZlYXR1cmVzLgoKYGBge3IsIGZpZy5oZWlnaHQ9NiwgZmlnLndpZHRoPTh9CmQyID0gcGxvdFBDQShvYmplY3Q9ZG5vdm85OC52c3QsIGludGdyb3VwPSdEaWFnbm9zaXMnLCByZXR1cm5EYXRhPUYpICsKICAgICB0aGVtZV9saW5lZHJhdygpICsgCiAgICAgbGFicyh0aXRsZT0nUGF0aWVudCBkaWFnbm9zaXMgb24gUENBJywgc3VidGl0bGU9cGFzdGUwKG5jb2woZG5vdm85OC52c3QpLCAnIHBhdGllbnRzLiA5OCUgQUEgc2ltaWxhcml0eScpKQpwbG90KGQyKQpgYGAKCgpgYGB7ciwgZmlnLmhlaWdodD02LCBmaWcud2lkdGg9OH0KZDIgPSBwbG90UENBKG9iamVjdD1kbm92bzk4LnZzdCwgaW50Z3JvdXA9J3NleCcsIHJldHVybkRhdGE9RikgKwogICAgIHRoZW1lX2xpbmVkcmF3KCkgKyAKICAgICBsYWJzKHRpdGxlPSdQYXRpZW50IGdlbmRlciBvbiBQQ0EnLCBzdWJ0aXRsZT1wYXN0ZTAobmNvbChkbm92bzk4LnZzdCksICcgcGF0aWVudHMuIDk4JSBBQSBzaW1pbGFyaXR5JykpCnBsb3QoZDIpCmBgYAoKYGBge3IsIGZpZy5oZWlnaHQ9NiwgZmlnLndpZHRoPTgsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0V9CmQyID0gcGxvdFBDQShvYmplY3Q9ZG5vdm85OC52c3QsIGludGdyb3VwPSdBZ2UuYXQuZGlhZ25vc2lzJywgcmV0dXJuRGF0YT1GKSArCiAgICAgdGhlbWVfbGluZWRyYXcoKSArIAogICAgIGxhYnModGl0bGU9J1BhdGllbnQgYWdlIG9uIFBDQScsIHN1YnRpdGxlPXBhc3RlMChuY29sKGRub3ZvOTgudnN0KSwgJyBwYXRpZW50cy4gOTglIEFBIHNpbWlsYXJpdHknKSkgKwogICAgIHNjYWxlX2NvbG9yX3ZpcmlkaXNfYyhvcHRpb24gPSAncGxhc21hJykKcGxvdChkMikKYGBgCgojIEZlYXR1cmUgYW5ub3RhdGlvbiBwaWUgY2hhcnRzCgpUaGUgZm9sbG93aW5nIHBsb3RzIHNob3cgdGhlIGFubm90YXRpb24gZnJvbSB0aGUgcHJva2FyaW90aWMgZ2VuZSBpZGVudGlmaWNhdGlvbiBwaXBlbGluZSBhY2NvcmRpbmcgdG8gdGhlIG1ham9yIGNhdGVnb3JpZXMgb2YgdGhlCkVuenltZSBDb21taXNzaW9uIG51bWJlciAoX0VDIG51bWJlcnNfKSAoc2VlIFtoZXJlXShodHRwczovL3d3dy5icmVuZGEtZW56eW1lcy5vcmcvYWxsX2VuenltZXMucGhwKSBvciBbaGVyZV0oaHR0cHM6Ly9lbnp5bWUuZXhwYXN5Lm9yZy9lbnp5bWUtc2VhcmNoLWVjLmh0bWwpKQphbmQgdGhlIFtDbHVzdGVycyBvZiBPcnRob2xvZ291cyBHZW5lc10oaHR0cHM6Ly93d3cubmNiaS5ubG0ubmloLmdvdi9yZXNlYXJjaC9jb2ctcHJvamVjdC8pIChfQ09Hc18pLgpGb3IgZ2VuZXMgd2l0aCBtdWx0aXBsZSBmdW5jdGlvbmFsIGFubm90YXRpb24gaW4gdGhlIENPRyBkYXRhYmFzZSwgdGhlIGZpcnN0IChtYWluKSBmdW5jdGlvbmFsIGFubm90YXRpb24gaXMgdXNlZC4KCmBgYHtyfQpjYWNoZUZpbGUgPSBwYXN0ZTAob3V0MkRpciwgJ215Y2FjaGVmaWxlLWFubm90YXRpb25zLlJEYXRhJykKaWYoIWZpbGUuZXhpc3RzKGNhY2hlRmlsZSkpIHsKICAjIyMjIEdldCB0aGUgUHJva2thIGFubm90YXRpb24gIyMjIwogIGFubm90cyA9IE5VTEwKICBmb3IoZmYgaW4gYygnQXJjaGFlYScsJ0JhY3RlcmlhJywnVmlydXNlcycpKSB7CiAgICB0c3ZGaWxlID0gcGFzdGUwKG91dDJEaXIsICdBbGxSZWYtJywgZmYsICcudHN2JykKICAgIHJyID0gZnJlYWQoZmlsZSA9IHRzdkZpbGUpCiAgICBhbm5vdHMgPSByYmluZChhbm5vdHMsIHJyW2Z0eXBlPT0nQ0RTJyxdKQogIH0KICAjIEFkZCB0aGUgcHJlZml4IHNvIHRoZXkgY2FuIGJlIGNvbXBhcmVkCiAgYW5ub3RzWywgbG9jdXNfdGFnIDo9IHBhc3RlMChsb2N1c190YWcsICdfZ2VuZScpXQogICMgU3BsaXQgdGhlIGhpZXJhcmNoaWNhbCBFbnp5bWUgbnVtYmVyCiAgbm5hID0gYW5ub3RzW25jaGFyKEVDX251bWJlcikgPiAwLCB3aGljaD1UXQogIHZ0YmwgPSBsYXBwbHkoYW5ub3RzJEVDX251bWJlcltubmFdLCB0c3Ryc3BsaXQsIHNwbGl0PScuJywgZml4ZWQ9VCkgCiAgdnRibCA9IHJiaW5kbGlzdCh2dGJsKQogIHNldChhbm5vdHMsIGk9bm5hLCBqPXBhc3RlMCgnRUMnLDE6NCksIHZhbHVlPXZ0YmwpCiAgCiAgIyMjIyBQcm9jZXNzIEVDIE51bWJlciBkZWZpbml0aW9ucyAjIyMjCiAgZWNGaWxlID0gcGFzdGUwKG91dDJEaXIsICdlbnp5bWUtZGF0YS54bWwuZ3onKQogIGFhID0geG1sMjo6cmVhZF94bWwoZWNGaWxlKQogICMgVGhlIDNyZCBhbmQgIHRhYmxlcyBhcmUgb2YgaW50ZXJlc3QKICAjIERpc2Fzc2VtYmxlIHRoZSBmaWxlIGJ5IGhhbmQKICAjIEF1eCBmdW5jdGlvbgogIGRlc2NyYW1ibGVfdCA8LSBmdW5jdGlvbihhcXEpIHsKICAgIHFxcSA9IGxhcHBseShhcXEsIGZ1bmN0aW9uKHopIHsKICAgICAgY29ucyA9IGxhcHBseSh4bWwyOjp4bWxfY2hpbGRyZW4oeiksIGZ1bmN0aW9uKHkpIHsgdG9TdHJpbmcoeG1sMjo6eG1sX2NvbnRlbnRzKHkpKSB9KQogICAgICBuYW1lcyhjb25zKSA9IHNhcHBseSh4bWwyOjp4bWxfY2hpbGRyZW4oeiksIGZ1bmN0aW9uKHkpIHsgdG9TdHJpbmcoeG1sMjo6eG1sX2F0dHJzKHkpKSB9LCBVU0UuTkFNRVMgPSBGKQogICAgICBjb25zCiAgICB9KQogICAgcXFxID0gcmJpbmRsaXN0KHFxcSwgZmlsbCA9IFQpCiAgICBuYW1lcyhxcXEpID0gZ3N1YignLCB0cnVlJywgJy5UJywgbmFtZXMocXFxKSkKICAgIHJldHVybihxcXEpCiAgfQogICMgVGhpcyBpcyB0aGUgdGFibGUgZGF0YQogIGEzID0geG1sMjo6eG1sX2NoaWxkcmVuKHhtbDI6OnhtbF9jaGlsZCh4bWwyOjp4bWxfY2hpbGQoYWEpLCA2KSkKICBhejMgPSBkZXNjcmFtYmxlX3QoYTMpCiAgCiAgYTIgPSB4bWwyOjp4bWxfY2hpbGRyZW4oeG1sMjo6eG1sX2NoaWxkKHhtbDI6OnhtbF9jaGlsZChhYSksIDQpKQogIGF6MiA9IGRlc2NyYW1ibGVfdChhMikKICAKICBFQyA9IGxpc3QocHJvdD1hejMsIGdyb3Vwcz1hejIpCiAgIyBUb3AgbGV2ZWwgY2xhc3NlcywgZm9yIGV4YW1wbGU6CiAgIyBhejJbc3Vic3ViY2xhc3M9PTAgJiBzdWJjbGFzcz09MCwgXQogIAogICMjIyMgUHJvY2VzcyB0aGUgQ09HIGRlZmluaXRpb25zICMjIyMKICAjIGh0dHBzOi8vZnRwLm5jYmkubmloLmdvdi9wdWIvQ09HL0NPRzIwMjAvZGF0YS9SZWFkbWUuMjAyMC0xMS0yNS50eHQKICAKICBjb2dGaWxlID0gcGFzdGUwKG91dDJEaXIsICdjb2ctMjAuZGVmLnRhYicpCiAgY29nID0gZnJlYWQoY29nRmlsZSwgaGVhZGVyPUYsIGNvbC5uYW1lcz1jKCdjb2dJZCcsJ2NhdGVnb3JpZXMnLCdjb2dOYW1lJywnZ2VuZScsJ3BhdGh3YXknLCdwdWJtZWRJZCcsJ3BkYklkJykpCiAgCiAgIyBGdW5jdGlvbmFsIGNhdGVnb3JpZXMKICBjb2d4ID0gZnJlYWQoaW5wdXQgPSAiCiAgICAgICAgICAgIEoJRkNDQ0ZDCVRyYW5zbGF0aW9uLCByaWJvc29tYWwgc3RydWN0dXJlIGFuZCBiaW9nZW5lc2lzCiAgICAgICAgICAgIEEJRkNEQ0ZDCVJOQSBwcm9jZXNzaW5nIGFuZCBtb2RpZmljYXRpb24KICAgICAgICAgICAgSwlGQ0RDRUMJVHJhbnNjcmlwdGlvbgogICAgICAgICAgICBMCUZDRENEQwlSZXBsaWNhdGlvbiwgcmVjb21iaW5hdGlvbiBhbmQgcmVwYWlyCiAgICAgICAgICAgIEIJRkNEQ0NDCUNocm9tYXRpbiBzdHJ1Y3R1cmUgYW5kIGR5bmFtaWNzCiAgICAgICAgICAgIEQJRkNGQ0RDCUNlbGwgY3ljbGUgY29udHJvbCwgY2VsbCBkaXZpc2lvbiwgY2hyb21vc29tZSBwYXJ0aXRpb25pbmcKICAgICAgICAgICAgWQlGQ0ZDQ0MJTnVjbGVhciBzdHJ1Y3R1cmUKICAgICAgICAgICAgVglGQ0ZDQkMJRGVmZW5zZSBtZWNoYW5pc21zCiAgICAgICAgICAgIFQJRkNGQ0FDCVNpZ25hbCB0cmFuc2R1Y3Rpb24gbWVjaGFuaXNtcwogICAgICAgICAgICBNCUVDRkNBQwlDZWxsIHdhbGwvbWVtYnJhbmUvZW52ZWxvcGUgYmlvZ2VuZXNpcwogICAgICAgICAgICBOCURDRkNBQwlDZWxsIG1vdGlsaXR5CiAgICAgICAgICAgIFoJQ0NGQ0FDCUN5dG9za2VsZXRvbgogICAgICAgICAgICBXCUJDRkNBQwlFeHRyYWNlbGx1bGFyIHN0cnVjdHVyZXMKICAgICAgICAgICAgVQlBQ0ZDQUMJSW50cmFjZWxsdWxhciB0cmFmZmlja2luZywgc2VjcmV0aW9uLCBhbmQgdmVzaWN1bGFyIHRyYW5zcG9ydAogICAgICAgICAgICBPCTlDRkNBQwlQb3N0dHJhbnNsYXRpb25hbCBtb2RpZmljYXRpb24sIHByb3RlaW4gdHVybm92ZXIsIGNoYXBlcm9uZXMKICAgICAgICAgICAgWAk5Q0ZDOUMJTW9iaWxvbWU6IHByb3BoYWdlcywgdHJhbnNwb3NvbnMKICAgICAgICAgICAgQwlCQ0ZDRkMJRW5lcmd5IHByb2R1Y3Rpb24gYW5kIGNvbnZlcnNpb24KICAgICAgICAgICAgRwlDQ0ZDRkMJQ2FyYm9oeWRyYXRlIHRyYW5zcG9ydCBhbmQgbWV0YWJvbGlzbQogICAgICAgICAgICBFCURDRkNGQwlBbWlubyBhY2lkIHRyYW5zcG9ydCBhbmQgbWV0YWJvbGlzbQogICAgICAgICAgICBGCURDRUNGQwlOdWNsZW90aWRlIHRyYW5zcG9ydCBhbmQgbWV0YWJvbGlzbQogICAgICAgICAgICBICURDRENGQwlDb2VuenltZSB0cmFuc3BvcnQgYW5kIG1ldGFib2xpc20KICAgICAgICAgICAgSQlEQ0NDRkMJTGlwaWQgdHJhbnNwb3J0IGFuZCBtZXRhYm9saXNtCiAgICAgICAgICAgIFAJQ0NDQ0ZDCUlub3JnYW5pYyBpb24gdHJhbnNwb3J0IGFuZCBtZXRhYm9saXNtCiAgICAgICAgICAgIFEJQkNDQ0ZDCVNlY29uZGFyeSBtZXRhYm9saXRlcyBiaW9zeW50aGVzaXMsIHRyYW5zcG9ydCBhbmQgY2F0YWJvbGlzbQogICAgICAgICAgICBSCUUwRTBFMAlHZW5lcmFsIGZ1bmN0aW9uIHByZWRpY3Rpb24gb25seQogICAgICAgICAgICBTCUNDQ0NDQwlGdW5jdGlvbiB1bmtub3duCiAgIiwgaGVhZGVyPUYsIGNvbC5uYW1lcz1jKCdDYXRlZ29yeScsJ2NvbG9yJywnRnVuY3Rpb24nKSkKICBjb2d4WyAsIGNvbG9yIDo9IHBhc3RlMCgnIycsIGNvbG9yKV0KICBDT0cgPSBsaXN0KGNsdXN0ZXJzPWNvZywgZ3JvdXBzPWNvZ3gpCiAgCiAgIyBTYXZlCiAgY2FjaGVGaWxlID0gcGFzdGUwKG91dERpciwgJ215Y2FjaGVmaWxlLWFubm90YXRpb25zLlJEYXRhJykKICBzYXZlKEVDLCBDT0csIGFubm90cywgZmlsZT1jYWNoZUZpbGUpCn0gZWxzZSB7CiAgbG9hZChjYWNoZUZpbGUpCn0KIyBGaXggY29sb3JzIGZvciBFQywgYm9ycm93IGZyb20gQ09HCnNldERUKEVDJGdyb3VwcykKc2V0KEVDJGdyb3Vwcywgaj0nY29sb3InLCB2YWx1ZT1saXN0KCcnKSkKc2V0KEVDJGdyb3VwcywgaT1FQyRncm91cHNbc3ViY2xhc3M9PTAsIHdoaWNoPVRdLCBqPSdjb2xvcicsIHZhbHVlPWxpc3Qoc2FtcGxlKENPRyRncm91cHMkY29sb3IsIG5yb3coRUMkZ3JvdXBzW3N1YmNsYXNzPT0wLF0pKSkpCmBgYAoKYGBge3J9CkRUOjpkYXRhdGFibGUoQ09HJGdyb3VwcywgY2FwdGlvbiA9ICdNYWpvciBjYXRlZ29yaWVzIG9mIENMdXN0ZXJzIG9mIE9ydGhvbG9nb3VzIEdlbmVzJykgJT4lCiAgICAgRFQ6OmZvcm1hdFN0eWxlKCdjb2xvcicsIGJhY2tncm91bmRDb2xvcj1EVDo6c3R5bGVWYWx1ZSgpKQpgYGAKCmBgYHtyfQpEVDo6ZGF0YXRhYmxlKEVDJGdyb3Vwc1tzdWJjbGFzcz09MCAmIHN1YnN1YmNsYXNzPT0wLCAuKGNsYXNzLCBjb2xvciwgaGVhZGluZyldLCBjYXB0aW9uID0gJ01ham9yIEVuenltZSBHcm91cHMnKSAlPiUKICAgICBEVDo6Zm9ybWF0U3R5bGUoJ2NvbG9yJywgYmFja2dyb3VuZENvbG9yPURUOjpzdHlsZVZhbHVlKCkpCmBgYAoKCiMjIE9uIGFsbCBmZWF0dXJlcyBpZGVudGlmaWVkCgpUaGVzZSBnaXZlIGNvbnRleHQgdG8gdGhlIHNlbGVjdGVkIGxpc3RzIGJlbG93LiBDb3JyZXNwb25kcyB0byBhbGwgYHIgbnJvdyhhbm5vdHMpYCBDRFMgaWRlbnRpZmllZCBmcm9tIG1ldGFnZW5vbWVzLCBubyBjb2xsYXBzaW5nIGJ5IHNlcXVlbmNlIHNpbWlsYXJpdHkuCgpgYGB7ciwgZmlnLmhlaWdodD02LCBmaWcud2lkdGg9OH0KIyMjIyBDb21wdXRlIG91ciBzdW1tYXJpZXMgIyMjIwojIEZpcnN0IGxldmVsIEVDIGNhdGVnb3JpZXMKZWMxbCA9IEVDJGdyb3Vwc1tzdWJzdWJjbGFzcz09MCAmIHN1YmNsYXNzPT0wLCAuKGNsYXNzLCBoZWFkaW5nLCBjb2xvcildCnNtcnkuRUMgPSBlYzFsW2Fubm90c1sgLCAuTiwgYnk9J0VDMSddLCBvbj0nY2xhc3M9PUVDMSddCnNldChzbXJ5LkVDLCBpPXdoaWNoKGlzLm5hKHNtcnkuRUMkY2xhc3MpKSwgaj1jKCdoZWFkaW5nJywnY29sb3InKSwgdmFsdWU9bGlzdCgnTi9BJywnI0FBQUFBQScpKQpzZXRrZXkoc21yeS5FQywgTikKIyBwbG90CiMgcDEgPSB0cmVlbWFwOjp0cmVlbWFwKHNtcnkuRUMsIGluZGV4ID0gJ2hlYWRpbmcnLCB2U2l6ZSA9ICdOJywgdGl0bGUgPSAnTWV0YWdlbm9taWMgZmVhdHVyZXMgYnkgZW56eW1lIGdyb3VwJykKCnBpZSh4PXNtcnkuRUMkTiwgbGFiZWxzPXNtcnkuRUMkaGVhZGluZywgY29sPXNtcnkuRUMkY29sb3IsIGluaXQuYW5nbGUgPSAxNDAsIGNsb2Nrd2lzZSA9IEYsIAogICAgbWFpbiA9ICdNZXRhZ2Vub21pYyBmZWF0dXJlcyBieSBlbnp5bWUgZ3JvdXAnKQpgYGAKCmBgYHtyLCBmaWcuaGVpZ2h0PTYsIGZpZy53aWR0aD04fQojIEZpcnN0IGNhdGVnb3J5IG9uIENPRwphbm4uY29nMSA9IENPRyRjbHVzdGVyc1thbm5vdHMsIC4oSUQ9bG9jdXNfdGFnLCBDYXRlZ29yeT1zdWJzdHIoY2F0ZWdvcmllcywxLDEpLCBjb2dOYW1lLCBjb2dJZCksIG9uPSdjb2dJZD09Q09HJ10Kc21yeS5jb2cgPSBDT0ckZ3JvdXBzW2Fubi5jb2cxWyAsIC5OLCBieT0nQ2F0ZWdvcnknXSwgb249J0NhdGVnb3J5J10Kc2V0KHNtcnkuY29nLCBpPXdoaWNoKGlzLm5hKHNtcnkuY29nJENhdGVnb3J5KSksIGo9YygnQ2F0ZWdvcnknLCdGdW5jdGlvbicsJ2NvbG9yJyksIHZhbHVlPWxpc3QoJycsICdOL0EnLCAnI0FBQUFBQScpKQpzZXRrZXkoc21yeS5jb2csIE4pCgojIE1ha2UgdGhlIHBsb3RzCiMgcDIgPSB0cmVlbWFwOjp0cmVlbWFwKHNtcnkuY29nLCBpbmRleD0nQ2F0ZWdvcnknLCB2U2l6ZSA9ICdOJywgdkNvbG9yID0gJ2NvbG9yJywgdHlwZT0nY29sb3InLCAKIyAgICAgICAgICAgICAgICAgICAgICAgdGl0bGUgPSAnTWV0YWdlbm9taWMgZmVhdHVyZXMgYnkgb3J0aG9sb2dvdXMgY2F0ZWdvcmllcyAoQ09HcyknKQoKbGFicyA9IHNtcnkuY29nJEZ1bmN0aW9uCmxhYnNbMTo5XSA9ICcnCmxhYnNbNF0gPSAnT3RoZXIgZnVuY3Rpb25hbCBncm91cHMnCmxhYnMgPSBnc3ViKCdQb3N0dHJhbnNsYXRpb25hbCcsICdQVCcsIGxhYnMpCnBpZSh4PXNtcnkuY29nJE4sIGxhYmVscz1sYWJzLCBjb2w9c21yeS5jb2ckY29sb3IsIGluaXQuYW5nbGUgPSAxNDAsIGNsb2Nrd2lzZSA9IEYsIG1haW4gPSAnTWV0YWdlbm9taWMgZmVhdHVyZXMgYnkgb3J0aG9sb2dvdXMgY2F0ZWdvcmllcyAoQ09HcyknLCBjZXg9MC43NSkKYGBgCgoKIyMgT24gZmVhdHVyZXMgZ3JvdXBlZCBhdCAxMDAlIHByb3RlaW4gc2VxdWVuY2Ugc2ltaWxhcml0eQoKYGBge3IsIGluY2x1ZGU9RkFMU0V9CiMgRnVuY3Rpb24gd2lsbCBjaGVjayBpZiBhbnkgYW5ub3RhdGlvbiBzZWxlY3RlZCBieSBtYWluIElEIChHZW5laWQpIGhhcyBlbXB0eSBjb2wxIGxhYmVscyB0aGF0IGNvdWxkIGJlIGZpbGxlZCBpZiBzZWxlY3RlZCBieSBsaW5rMSBjb2x1bW4KY2hlY2tUb0ZpbGwgPC0gZnVuY3Rpb24oYW5ubywgckQsIGNvbDEsIGxpbmsxKSB7CiAgIyBicm93c2VyKCkKICBueSA9IG1hdGNoKHJEJEdlbmVpZCwgYW5ubyRsb2N1c190YWcpCiAgbnggPSB3aGljaChuY2hhcih1bmxpc3QoYW5ub1tueSwgLi5jb2wxXSwgdXNlLm5hbWVzPUYpKSA9PSAwKQogIG56ID0gaW50ZWdlcigwKQogIGlmKGxlbmd0aChueCkgPiAwKSB7CiAgICBudSA9IGFubm9bckRbbngsXSwgb249cGFzdGUwKCdsb2N1c190YWc9PScsIGxpbmsxKSwgd2hpY2g9VF0KICAgIG56ID0gd2hpY2gobmNoYXIodW5saXN0KGFubm9bbnUsIC4uY29sMV0sIHVzZS5uYW1lcz1GKSkgPiAwKQogICAgaWYobGVuZ3RoKG56KSA+IDApIHsKICAgICAgZmxvZy53YXJuKCIlZCAlcyBlbXB0eSwgJWQgb2Ygd2hpY2ggY291bGQgZmlsbGVkIGZyb20gJXMiLCBsZW5ndGgobngpLCBjb2wxLCBsZW5ndGgobnopLCBsaW5rMSkKICAgICAgcmV0dXJuKFRSVUUpCiAgICB9CiAgfQogICMgTHVja3kgd2UgaGF2ZSBub25lCiAgZmxvZy5pbmZvKCIlczogJWQgJXMgZW1wdHksIDAgdG8gZmlsbCIsIGxpbmsxLCBsZW5ndGgobngpLCBjb2wxKQogIHJldHVybihGQUxTRSkKfQoKIyBGdW5jdGlvbiB3aWxsIGNoZWNrIGlmIGFubm90YXRpb25zIHdpdGggY29sMSBsYWJlbHMgaGF2ZSBzYW1lIGxhYmVsIHdoZW4gc2VsZWN0ZWQgYnkgR2VuZWlkIG9yIGxpbmsxCmNoZWNrQ29uc2lzdGVudCA8LSBmdW5jdGlvbihhbm5vLCByRCwgY29sMSwgbGluazEpIHsKICAjIGJyb3dzZXIoKQogIHRvY2hlY2sxID0gYW5ub1tyRCwgb249J2xvY3VzX3RhZz09R2VuZWlkJ10KICBueCA9IHdoaWNoKG5jaGFyKHVubGlzdCh0b2NoZWNrMVsgLCAuLmNvbDFdLCB1c2UubmFtZXMgPSBGKSkgPiAwKQogIHRvY2hlY2sxID0gdG9jaGVjazFbbngsIC5TRCwgLlNEY29scz1jKCdsb2N1c190YWcnLCBjb2wxKV0KICB0b2NoZWNrMiA9IGFubm9bckQsIG9uPXBhc3RlMCgnbG9jdXNfdGFnPT0nLCBsaW5rMSldCiAgbnkgPSB3aGljaChuY2hhcih1bmxpc3QodG9jaGVjazJbICwgLi5jb2wxXSwgdXNlLm5hbWVzID0gRikpID4gMCkKICB0b2NoZWNrMiA9IHRvY2hlY2syW255LCAuU0QsIC5TRGNvbHM9YygnbG9jdXNfdGFnJywgJ0dlbmVpZCcsIGNvbDEpXQogIHNzcyA9IHNwcmludGYoInRvY2hlY2syW3RvY2hlY2sxLCAlcyAhPSBpLiVzLCBvbj0nR2VuZWlkPT1sb2N1c190YWcnXSIsIGNvbDEsIGNvbDEpCiAgbnogPSB3aGljaChldmFsKHBhcnNlKHRleHQ9c3NzKSkpCiAgZmxvZy5pbmZvKCI+PiAlczogJWQgZGlmZmVyIGluICVzIiwgbGluazEsIGxlbmd0aChueiksIGNvbDEpCiAgaWYobGVuZ3RoKG56KSkgewogICAgcmV0dXJuKFRSVUUpCiAgfQogIHJldHVybihGQUxTRSkKfQpgYGAKCmBgYHtyLCBpbmNsdWRlPUZBTFNFfQpyZCA9IGFzLmRhdGEudGFibGUocm93RGF0YShkbm92bzEwMC52c3QpKQoKIyBGb3IgZGVub3ZvMTAwLCB0aGUgbGlua2luZyBvbiBwcm90X3VpZCBzaG91bGQgYmUgaXJyZWxldmFudApjaGVja1RvRmlsbChhbm5vID0gYW5ub3RzLCByRCA9IHJkLCBjb2wxID0gJ0VDX251bWJlcicsIGxpbmsxID0gJ29yaWdfaWQnKQpjaGVja1RvRmlsbChhbm5vID0gYW5ub3RzLCByRCA9IHJkLCBjb2wxID0gJ0NPRycsICAgICAgIGxpbmsxID0gJ29yaWdfaWQnKQpjaGVja1RvRmlsbChhbm5vID0gYW5ub3RzLCByRCA9IHJkLCBjb2wxID0gJ0VDX251bWJlcicsIGxpbmsxID0gJ251Y191aWQnKQpjaGVja1RvRmlsbChhbm5vID0gYW5ub3RzLCByRCA9IHJkLCBjb2wxID0gJ0NPRycsICAgICAgIGxpbmsxID0gJ251Y191aWQnKQpjaGVja1RvRmlsbChhbm5vID0gYW5ub3RzLCByRCA9IHJkLCBjb2wxID0gJ0VDX251bWJlcicsIGxpbmsxID0gJ3Byb3RfdWlkJykKY2hlY2tUb0ZpbGwoYW5ubyA9IGFubm90cywgckQgPSByZCwgY29sMSA9ICdDT0cnLCAgICAgICBsaW5rMSA9ICdwcm90X3VpZCcpCgpjaGVja0NvbnNpc3RlbnQoYW5ubyA9IGFubm90cywgckQgPSByZCwgY29sMSA9ICdFQ19udW1iZXInLCBsaW5rMSA9ICdvcmlnX2lkJykKY2hlY2tDb25zaXN0ZW50KGFubm8gPSBhbm5vdHMsIHJEID0gcmQsIGNvbDEgPSAnQ09HJywgICAgICAgbGluazEgPSAnb3JpZ19pZCcpCmNoZWNrQ29uc2lzdGVudChhbm5vID0gYW5ub3RzLCByRCA9IHJkLCBjb2wxID0gJ0VDX251bWJlcicsIGxpbmsxID0gJ251Y191aWQnKQpjaGVja0NvbnNpc3RlbnQoYW5ubyA9IGFubm90cywgckQgPSByZCwgY29sMSA9ICdDT0cnLCAgICAgICBsaW5rMSA9ICdudWNfdWlkJykKY2hlY2tDb25zaXN0ZW50KGFubm8gPSBhbm5vdHMsIHJEID0gcmQsIGNvbDEgPSAnRUNfbnVtYmVyJywgbGluazEgPSAncHJvdF91aWQnKQpjaGVja0NvbnNpc3RlbnQoYW5ubyA9IGFubm90cywgckQgPSByZCwgY29sMSA9ICdDT0cnLCAgICAgICBsaW5rMSA9ICdwcm90X3VpZCcpCgpteWFubm90ID0gYW5ub3RzW3JkLCBvbj0nbG9jdXNfdGFnPT1HZW5laWQnXQoKYGBgCgpUaGUgZm9sbG93aW5nIHBsb3RzIGRlcGljdCBhbm5vdGF0aW9uIHByb3BvcnRpb24gb24gdGhlIHNlcXVlbmNlcyBpZGVudGlmaWVkIGF0IDEwMCUgcHJvdGVpbiBzZXF1ZW5jZSBzaW1pbGFyaXR5LCB0aGF0IGFsc28gcGFzcyB0aGUgbWluaW11bSByZWFkIGNvdW50IGZpbHRlciBmb3IgZGlmZmVyZW50aWFsIGV4cHJlc3Npb24gYW5hbHlzaXMuCgpgYGB7ciwgZmlnLmhlaWdodD02LCBmaWcud2lkdGg9OH0KIyMjIyBDb21wdXRlIG91ciBzdW1tYXJpZXMgIyMjIwojIEZpcnN0IGxldmVsIEVDIGNhdGVnb3JpZXMKZWMxbCA9IEVDJGdyb3Vwc1tzdWJzdWJjbGFzcz09MCAmIHN1YmNsYXNzPT0wLCAuKGNsYXNzLCBoZWFkaW5nLCBjb2xvcildCnNtcnkuRUMgPSBlYzFsW215YW5ub3RbICwgLk4sIGJ5PSdFQzEnXSwgb249J2NsYXNzPT1FQzEnXQpzZXQoc21yeS5FQywgaT13aGljaChpcy5uYShzbXJ5LkVDJGNsYXNzKSksIGo9YygnaGVhZGluZycsJ2NvbG9yJyksIHZhbHVlPWxpc3QoJ04vQScsJyNBQUFBQUEnKSkKc2V0a2V5KHNtcnkuRUMsIE4pCiMgcGxvdAojIHAxID0gdHJlZW1hcDo6dHJlZW1hcChzbXJ5LkVDLCBpbmRleCA9ICdoZWFkaW5nJywgdlNpemUgPSAnTicsIHRpdGxlPXNwcmludGYoJ01ldGFnZW5vbWljIGZlYXR1cmVzICgxMDAlJSBzcywgJWQgc2VxcykgYnkgZW56eW1lIGdyb3VwJywgbnJvdyhteWFubm90KSkpCgpwaWUoeD1zbXJ5LkVDJE4sIGxhYmVscz1zbXJ5LkVDJGhlYWRpbmcsIGNvbD1zbXJ5LkVDJGNvbG9yLCBpbml0LmFuZ2xlID0gMTQwLCBjbG9ja3dpc2UgPSBGLCAKICAgIG1haW49c3ByaW50ZignTWV0YWdlbm9taWMgZmVhdHVyZXMgKDEwMCUlIHNzLCAlZCBzZXFzKSBieSBlbnp5bWUgZ3JvdXAnLCBucm93KG15YW5ub3QpKSkKYGBgCgoKYGBge3IsIGZpZy5oZWlnaHQ9NiwgZmlnLndpZHRoPTh9CiMgRmlyc3QgY2F0ZWdvcnkgb24gQ09HCmFubi5jb2cxID0gQ09HJGNsdXN0ZXJzW215YW5ub3QsIC4oSUQ9bG9jdXNfdGFnLCBDYXRlZ29yeT1zdWJzdHIoY2F0ZWdvcmllcywxLDEpLCBjb2dOYW1lLCBjb2dJZCksIG9uPSdjb2dJZD09Q09HJ10Kc21yeS5jb2cgPSBDT0ckZ3JvdXBzW2Fubi5jb2cxWyAsIC5OLCBieT0nQ2F0ZWdvcnknXSwgb249J0NhdGVnb3J5J10Kc2V0KHNtcnkuY29nLCBpPXdoaWNoKGlzLm5hKHNtcnkuY29nJENhdGVnb3J5KSksIGo9YygnQ2F0ZWdvcnknLCdGdW5jdGlvbicsJ2NvbG9yJyksIHZhbHVlPWxpc3QoJycsICdOL0EnLCAnI0FBQUFBQScpKQpzZXRrZXkoc21yeS5jb2csIE4pCgojIE1ha2UgdGhlIHBsb3RzCiMgcDIgPSB0cmVlbWFwOjp0cmVlbWFwKHNtcnkuY29nLCBpbmRleD0nQ2F0ZWdvcnknLCB2U2l6ZSA9ICdOJywgdkNvbG9yID0gJ2NvbG9yJywgdHlwZT0nY29sb3InLCAKIyAgICAgICAgICAgICAgICAgICAgICAgdGl0bGU9c3ByaW50ZignTWV0YWdlbm9taWMgZmVhdHVyZXMgKDEwMCUlIHNzLCAlZCBzZXFzKSBieSBvcnRob2xvZ291cyBjYXRlZ29yaWVzIChDT0dzKScsIG5yb3cobXlhbm5vdCkpKQoKbGFicyA9IHNtcnkuY29nJEZ1bmN0aW9uCmxhYnNbMTo5XSA9ICcnCmxhYnNbNF0gPSAnT3RoZXIgZnVuY3Rpb25hbCBncm91cHMnCmxhYnMgPSBnc3ViKCdQb3N0dHJhbnNsYXRpb25hbCcsICdQVCcsIGxhYnMpCnBpZSh4PXNtcnkuY29nJE4sIGxhYmVscz1sYWJzLCBjb2w9c21yeS5jb2ckY29sb3IsIGluaXQuYW5nbGUgPSAxNDAsIGNsb2Nrd2lzZSA9IEYsCiAgICBtYWluPXNwcmludGYoJ01ldGFnZW5vbWljIGZlYXR1cmVzICgxMDAlJSBzcywgJWQgc2VxcykgYnkgb3J0aG9sb2dvdXMgY2F0ZWdvcmllcyAoQ09HcyknLCBucm93KG15YW5ub3QpKSwgY2V4PTAuNzUpCmBgYAoKCiMjIE9uIGZlYXR1cmVzIGdyb3VwZWQgYXQgOTglIHNlcXVlbmNlIHNpbWlsYXJpdHkKCmBgYHtyLCBpbmNsdWRlPUZBTFNFfQpyZCA9IGFzLmRhdGEudGFibGUocm93RGF0YShkbm92bzk4LnZzdCkpCgojIEZvciBkZW5vdm85OCwgdGhlIGxpbmtpbmcgb24gcGNkOTggc2hvdWxkIGJlIGlycmVsZXZhbnQKY2hlY2tUb0ZpbGwoYW5ubyA9IGFubm90cywgckQgPSByZCwgY29sMSA9ICdFQ19udW1iZXInLCBsaW5rMSA9ICdvcmlnX2lkJykKY2hlY2tUb0ZpbGwoYW5ubyA9IGFubm90cywgckQgPSByZCwgY29sMSA9ICdDT0cnLCAgICAgICBsaW5rMSA9ICdvcmlnX2lkJykKY2hlY2tUb0ZpbGwoYW5ubyA9IGFubm90cywgckQgPSByZCwgY29sMSA9ICdFQ19udW1iZXInLCBsaW5rMSA9ICdudWNfdWlkJykKY2hlY2tUb0ZpbGwoYW5ubyA9IGFubm90cywgckQgPSByZCwgY29sMSA9ICdDT0cnLCAgICAgICBsaW5rMSA9ICdudWNfdWlkJykKY2hlY2tUb0ZpbGwoYW5ubyA9IGFubm90cywgckQgPSByZCwgY29sMSA9ICdFQ19udW1iZXInLCBsaW5rMSA9ICdwcm90X3VpZCcpCmNoZWNrVG9GaWxsKGFubm8gPSBhbm5vdHMsIHJEID0gcmQsIGNvbDEgPSAnQ09HJywgICAgICAgbGluazEgPSAncHJvdF91aWQnKQpjaGVja1RvRmlsbChhbm5vID0gYW5ub3RzLCByRCA9IHJkLCBjb2wxID0gJ0VDX251bWJlcicsIGxpbmsxID0gJ2NkOTgnKQpjaGVja1RvRmlsbChhbm5vID0gYW5ub3RzLCByRCA9IHJkLCBjb2wxID0gJ0NPRycsICAgICAgIGxpbmsxID0gJ2NkOTgnKQoKY2hlY2tDb25zaXN0ZW50KGFubm8gPSBhbm5vdHMsIHJEID0gcmQsIGNvbDEgPSAnRUNfbnVtYmVyJywgbGluazEgPSAnb3JpZ19pZCcpCmNoZWNrQ29uc2lzdGVudChhbm5vID0gYW5ub3RzLCByRCA9IHJkLCBjb2wxID0gJ0NPRycsICAgICAgIGxpbmsxID0gJ29yaWdfaWQnKQpjaGVja0NvbnNpc3RlbnQoYW5ubyA9IGFubm90cywgckQgPSByZCwgY29sMSA9ICdFQ19udW1iZXInLCBsaW5rMSA9ICdudWNfdWlkJykKY2hlY2tDb25zaXN0ZW50KGFubm8gPSBhbm5vdHMsIHJEID0gcmQsIGNvbDEgPSAnQ09HJywgICAgICAgbGluazEgPSAnbnVjX3VpZCcpCmNoZWNrQ29uc2lzdGVudChhbm5vID0gYW5ub3RzLCByRCA9IHJkLCBjb2wxID0gJ0VDX251bWJlcicsIGxpbmsxID0gJ3Byb3RfdWlkJykKY2hlY2tDb25zaXN0ZW50KGFubm8gPSBhbm5vdHMsIHJEID0gcmQsIGNvbDEgPSAnQ09HJywgICAgICAgbGluazEgPSAncHJvdF91aWQnKQpjaGVja0NvbnNpc3RlbnQoYW5ubyA9IGFubm90cywgckQgPSByZCwgY29sMSA9ICdFQ19udW1iZXInLCBsaW5rMSA9ICdjZDk4JykKY2hlY2tDb25zaXN0ZW50KGFubm8gPSBhbm5vdHMsIHJEID0gcmQsIGNvbDEgPSAnQ09HJywgICAgICAgbGluazEgPSAnY2Q5OCcpCgpteWFubm90ID0gYW5ub3RzW3JkLCBvbj0nbG9jdXNfdGFnPT1HZW5laWQnXQpgYGAKClRoZSBmb2xsb3dpbmcgcGxvdHMgZGVwaWN0IHRoZSBhbm5vdGF0aW9uIHByb3BvcnRpb24gb24gdGhlIHNlcXVlbmNlcyBpZGVudGlmaWVkIGF0IDk4JSBwcm90ZWluIHNlcXVlbmNlIHNpbWlsYXJpdHksIHRoYXQgYWxzbyBwYXNzIHRoZSBtaW5pbXVtIHJlYWQgY291bnQgZmlsdGVyIGZvciBkaWZmZXJlbnRpYWwgZXhwcmVzc2lvbiBhbmFseXNpcy4KCmBgYHtyLCBmaWcuaGVpZ2h0PTYsIGZpZy53aWR0aD04fQojIyMjIENvbXB1dGUgb3VyIHN1bW1hcmllcyAjIyMjCiMgRmlyc3QgbGV2ZWwgRUMgY2F0ZWdvcmllcwplYzFsID0gRUMkZ3JvdXBzW3N1YnN1YmNsYXNzPT0wICYgc3ViY2xhc3M9PTAsIC4oY2xhc3MsIGhlYWRpbmcsIGNvbG9yKV0Kc21yeS5FQyA9IGVjMWxbbXlhbm5vdFsgLCAuTiwgYnk9J0VDMSddLCBvbj0nY2xhc3M9PUVDMSddCnNldChzbXJ5LkVDLCBpPXdoaWNoKGlzLm5hKHNtcnkuRUMkY2xhc3MpKSwgaj1jKCdoZWFkaW5nJywnY29sb3InKSwgdmFsdWU9bGlzdCgnTi9BJywnI0FBQUFBQScpKQpzZXRrZXkoc21yeS5FQywgTikKIyBwbG90CiMgcDEgPSB0cmVlbWFwOjp0cmVlbWFwKHNtcnkuRUMsIGluZGV4ID0gJ2hlYWRpbmcnLCB2U2l6ZSA9ICdOJywgdGl0bGU9c3ByaW50ZignTWV0YWdlbm9taWMgZmVhdHVyZXMgKDEwMCUlIHNzLCAlZCBzZXFzKSBieSBlbnp5bWUgZ3JvdXAnLCBucm93KG15YW5ub3QpKSkKCnBpZSh4PXNtcnkuRUMkTiwgbGFiZWxzPXNtcnkuRUMkaGVhZGluZywgY29sPXNtcnkuRUMkY29sb3IsIGluaXQuYW5nbGUgPSAxNDAsIGNsb2Nrd2lzZSA9IEYsIAogICAgbWFpbj1zcHJpbnRmKCdNZXRhZ2Vub21pYyBmZWF0dXJlcyAoOTglJSBzcywgJWQgc2VxcykgYnkgZW56eW1lIGdyb3VwJywgbnJvdyhteWFubm90KSkpCmBgYAoKCmBgYHtyLCBmaWcuaGVpZ2h0PTYsIGZpZy53aWR0aD04fQojIEZpcnN0IGNhdGVnb3J5IG9uIENPRwphbm4uY29nMSA9IENPRyRjbHVzdGVyc1tteWFubm90LCAuKElEPWxvY3VzX3RhZywgQ2F0ZWdvcnk9c3Vic3RyKGNhdGVnb3JpZXMsMSwxKSwgY29nTmFtZSwgY29nSWQpLCBvbj0nY29nSWQ9PUNPRyddCnNtcnkuY29nID0gQ09HJGdyb3Vwc1thbm4uY29nMVsgLCAuTiwgYnk9J0NhdGVnb3J5J10sIG9uPSdDYXRlZ29yeSddCnNldChzbXJ5LmNvZywgaT13aGljaChpcy5uYShzbXJ5LmNvZyRDYXRlZ29yeSkpLCBqPWMoJ0NhdGVnb3J5JywnRnVuY3Rpb24nLCdjb2xvcicpLCB2YWx1ZT1saXN0KCcnLCAnTi9BJywgJyNBQUFBQUEnKSkKc2V0a2V5KHNtcnkuY29nLCBOKQoKIyBNYWtlIHRoZSBwbG90cwojIHAyID0gdHJlZW1hcDo6dHJlZW1hcChzbXJ5LmNvZywgaW5kZXg9J0NhdGVnb3J5JywgdlNpemUgPSAnTicsIHZDb2xvciA9ICdjb2xvcicsIHR5cGU9J2NvbG9yJywgCiMgICAgICAgICAgICAgICAgICAgICAgIHRpdGxlPXNwcmludGYoJ01ldGFnZW5vbWljIGZlYXR1cmVzICg5OCUlIHNzLCAlZCBzZXFzKSBieSBvcnRob2xvZ291cyBjYXRlZ29yaWVzIChDT0dzKScsIG5yb3cobXlhbm5vdCkpKQoKbGFicyA9IHNtcnkuY29nJEZ1bmN0aW9uCmxhYnNbMTo5XSA9ICcnCmxhYnNbNF0gPSAnT3RoZXIgZnVuY3Rpb25hbCBncm91cHMnCmxhYnMgPSBnc3ViKCdQb3N0dHJhbnNsYXRpb25hbCcsICdQVCcsIGxhYnMpCnBpZSh4PXNtcnkuY29nJE4sIGxhYmVscz1sYWJzLCBjb2w9c21yeS5jb2ckY29sb3IsIGluaXQuYW5nbGUgPSAxNDAsIGNsb2Nrd2lzZSA9IEYsCiAgICBtYWluPXNwcmludGYoJ01ldGFnZW5vbWljIGZlYXR1cmVzICg5OCUlIHNzLCAlZCBzZXFzKSBieSBvcnRob2xvZ291cyBjYXRlZ29yaWVzIChDT0dzKScsIG5yb3cobXlhbm5vdCkpLCBjZXg9MC43NSkKYGBgCgojIyBPbiBjb21tb24gdG9wIGRpZmZlcmVudGlhbGx5IGV4cHJlc3NlZCByZXN1bHRzIGZyb20gREVTZXEyIGFuZCBWYXJpYW5jZSBQYXJ0aXRpb24KClRoZSBmZWF0dXJlIHR5cGUgcGllIGNoYXJ0cyBjb3JyZXNwb25kIHRvIHRoZSBjb21tb24gZmVhdHVyZXMgZnJvbSB0aGUgdG9wIDUwMDAgcmVzdWx0cyBvZiBlYWNoIG1ldGhvZCwgYXQgOTglIHNlcXVlbmNlIHNpbWlsYXJpdHkuICAKVGhlIFZlbm4gZGlhZ3JhbXMgaWxsdXN0cmF0ZSB0aGUgb3ZlcmxhcCBiZXR3ZWVuIHJlc3VsdHMgYXQgdmFyaW91cyB0b3AgcmVzdWx0cyBudW1iZXJzLgoKYGBge3IsIGZpZy5oZWlnaHQ9NiwgZmlnLndpZHRoPTEwfQpteWNhc2VzID0gYygnQ0Qtbm9uSUJEJywgJ1VDLW5vbklCRCcsICdIaWdoLUxvdycpCm15Y2FzZSA9ICdDRC1ub25JQkQnCmZvcihteWNhc2UgaW4gbXljYXNlcykgewogIGlmKG15Y2FzZSA9PSAnQ0Qtbm9uSUJEJykgewogICAgcmVzdWx0RmlsZURFU2VxID0gcGFzdGUwKGRleHBEaXIwLCAnZGlhZ25vc2lzLScsIG15Y2FzZSwgJy1jZDk4LmNzdi5neicpCiAgICByZXN1bHRGaWxlVlAgPSBwYXN0ZTAoZGV4cERpcjEsICdkaWFnbm9zaXMtQ0QtdmFycGFydC12b29tLmNkOTguY3N2Lmd6JykKICB9IGVsc2UgaWYobXljYXNlID09ICdVQy1ub25JQkQnKSB7CiAgICByZXN1bHRGaWxlREVTZXEgPSBwYXN0ZTAoZGV4cERpcjAsICdkaWFnbm9zaXMtJywgbXljYXNlLCAnLWNkOTguY3N2Lmd6JykKICAgIHJlc3VsdEZpbGVWUCA9IHBhc3RlMChkZXhwRGlyMSwgJ2RpYWdub3Npcy1VQy12YXJwYXJ0LXZvb20uY2Q5OC5jc3YuZ3onKQogIH0gZWxzZSB7CiAgICByZXN1bHRGaWxlREVTZXEgPSBwYXN0ZTAoZGV4cERpcjAsICdBY3Rpdml0eUxldmVsLScsIG15Y2FzZSwgJy1jZDk4LmNzdi5neicpCiAgICByZXN1bHRGaWxlVlAgPSBwYXN0ZTAoZGV4cERpcjIsICdhY3Rpdml0eS1IaWdoLXZhcnBhcnQtdm9vbS5jZDk4LmNzdi5neicpCiAgfQogIHJlc0RTID0gZnJlYWQocmVzdWx0RmlsZURFU2VxKQogIHJlc1ZQID0gZnJlYWQocmVzdWx0RmlsZVZQKQogIHJlc0RTWywgYWwyZmMgOj0gLWFicyhsb2cyRkMpXQogIHJlc1ZQWywgQiA6PSAtQl0KICAjIFNldCBrZXlzIGZvciBpbnRlcnNlY3Rpb24KICBzZXRrZXkocmVzRFMsIHB2YWx1ZSwgYWwyZmMpCiAgc2V0a2V5KHJlc1ZQLCBQLlZhbHVlLCBCKQogIAogIGdsaXMgPSBpbGFicyA9IE5VTEwKICBmb3IobnRoIGluIGMoNTAsIDUwMCwgMjAwMCwgNTAwMCkpIHsKICAgIGlzZWMgPSBpbnRlcnNlY3QocmVzVlBbMTpudGgsIEdlbmVpZF0sIHJlc0RTWzE6bnRoLCBnZW5lX2lkXSkKICAgIGZsb2cuaW5mbygnICAlcyB0b3AgJWc6XHQgJWQgY29tbW9uJywgbXljYXNlLCBudGgsIGxlbmd0aChpc2VjKSkKICAgIGlsaXMgPSBsaXN0KHJlc1ZQWzE6bnRoLCBHZW5laWRdLCByZXNEU1sxOm50aCwgZ2VuZV9pZF0pCiAgICBzbmFtZXMgPSBjKCdERVNlcScsJ3ZhclBhcnQnKQogICAgZ2cgPSB2ZW5uOjp2ZW5uKGlsaXMsIHNuYW1lcz1zbmFtZXMsIGdncGxvdD1ULCB6Y29sb3I9J3N0eWxlJywgYm94PUYpICsKICAgICAgdGhlbWVfdm9pZCgpICMgKwogICAgICAjIGxhYnModGl0bGU9c3ByaW50ZignJXM6IGNvbW1vbiBhbW9uZyB0b3AgJWQnLCBteWNhc2UsIG50aCkpCiAgICBpbGFicyA9IGMoaWxhYnMsIHNwcmludGYoJyVzOiBjb21tb24gYW1vbmcgdG9wICVkJywgbXljYXNlLCBudGgpKQogICAgZ2xpcyA9IGMoZ2xpcywgbGlzdChnZykpCiAgfQogICMgenogPSBncmlkRXh0cmE6OmFycmFuZ2VHcm9iKGdyb2JzPWdsaXMsIG5jb2w9MikKICB6eiA9IGNvd3Bsb3Q6OnBsb3RfZ3JpZChwbG90bGlzdD1nbGlzLCBuY29sPTIsIGxhYmVscz1pbGFicywgZ3JlZWR5PUYsCiAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbF9mb250ZmFtaWx5PSdDb21mb3J0YWEnLCBsYWJlbF9zaXplPTExLCBsYWJlbF9mb250ZmFjZT0ncGxhaW4nLCBsYWJlbF95PTAuOTcsIGxhYmVsX3g9LS4yKQogIHBsb3QoenopCiAgCiAgIyBpc2VjIGNvbnRhaW5zIHRoZSBpbnRlcnNlY3Rpb24gb24gNTAwMCB0b3AgcmVzdWx0cyBhdCBlbmQgb2YgbG9vcAogIG15YW5ub3QgPSBhbm5vdHNbaXNlYywgb249J2xvY3VzX3RhZyddCiAgCiAgIyMjIyBDb21wdXRlIG91ciBzdW1tYXJpZXMgIyMjIwogIHNtcnkuRUMgPSBlYzFsW215YW5ub3RbICwgLk4sIGJ5PSdFQzEnXSwgb249J2NsYXNzPT1FQzEnXQogIHNldChzbXJ5LkVDLCBpPXdoaWNoKGlzLm5hKHNtcnkuRUMkY2xhc3MpKSwgaj1jKCdoZWFkaW5nJywnY29sb3InKSwgdmFsdWU9bGlzdCgnTi9BJywnI0FBQUFBQScpKQogIHNldGtleShzbXJ5LkVDLCBOKQogICMgcGxvdAogICMgcDEgPSB0cmVlbWFwOjp0cmVlbWFwKHNtcnkuRUMsIGluZGV4ID0gJ2hlYWRpbmcnLCB2U2l6ZSA9ICdOJywgCiAgIyAgICAgICAgICAgICAgICAgICAgICAgdGl0bGU9c3ByaW50ZignRW56eW1lIGdyb3VwIG9uIDk4JSUgc3MgREUgZmVhdHVyZXMgKCVkIHNlcXMpLCAlcycsIG5yb3cobXlhbm5vdCksIG15Y2FzZSkpCiAgCiAgcGllKHg9c21yeS5FQyROLCBsYWJlbHM9c21yeS5FQyRoZWFkaW5nLCBjb2w9c21yeS5FQyRjb2xvciwgaW5pdC5hbmdsZSA9IDE0MCwgY2xvY2t3aXNlID0gRiwgCiAgICAgIG1haW49c3ByaW50ZignJXM6IEVuenltZSBncm91cCBmb3IgJWQgY29tbW9uIHNlcXMgYXQgOTglJSBzcycsIG15Y2FzZSwgbnJvdyhteWFubm90KSkpCiAgCiAgIyBGaXJzdCBjYXRlZ29yeSBvbiBDT0cKICBhbm4uY29nMSA9IENPRyRjbHVzdGVyc1tteWFubm90LCAuKElEPWxvY3VzX3RhZywgQ2F0ZWdvcnk9c3Vic3RyKGNhdGVnb3JpZXMsMSwxKSwgY29nTmFtZSwgY29nSWQpLCBvbj0nY29nSWQ9PUNPRyddCiAgc21yeS5jb2cgPSBDT0ckZ3JvdXBzW2Fubi5jb2cxWyAsIC5OLCBieT0nQ2F0ZWdvcnknXSwgb249J0NhdGVnb3J5J10KICBzZXQoc21yeS5jb2csIGk9d2hpY2goaXMubmEoc21yeS5jb2ckQ2F0ZWdvcnkpKSwgaj1jKCdDYXRlZ29yeScsJ0Z1bmN0aW9uJywnY29sb3InKSwgdmFsdWU9bGlzdCgnJywgJ04vQScsICcjQUFBQUFBJykpCiAgc2V0a2V5KHNtcnkuY29nLCBOKQogIAogICMgTWFrZSB0aGUgcGxvdHMKICAjIHAyID0gdHJlZW1hcDo6dHJlZW1hcChzbXJ5LmNvZywgaW5kZXg9J0NhdGVnb3J5JywgdlNpemUgPSAnTicsIHZDb2xvciA9ICdjb2xvcicsIHR5cGU9J2NvbG9yJywgCiAgIyAgICAgICAgICAgICAgICAgICAgICAgdGl0bGU9c3ByaW50ZignTWV0YWdlbm9taWMgZmVhdHVyZXMgKDk4JSUgc3MsICVkIHNlcXMpIGJ5IG9ydGhvbG9nb3VzIGNhdGVnb3JpZXMgKENPR3MpJywgbnJvdyhteWFubm90KSkpCiAgCiAgbGFicyA9IHNtcnkuY29nJEZ1bmN0aW9uCiAgbGFic1sxOjldID0gJycKICBsYWJzWzRdID0gJ090aGVyIGZ1bmN0aW9uYWwgZ3JvdXBzJwogIGxhYnMgPSBnc3ViKCdQb3N0dHJhbnNsYXRpb25hbCcsICdQVCcsIGxhYnMpCiAgcGllKHg9c21yeS5jb2ckTiwgbGFiZWxzPWxhYnMsIGNvbD1zbXJ5LmNvZyRjb2xvciwgaW5pdC5hbmdsZSA9IDE0MCwgY2xvY2t3aXNlID0gRiwKICAgICAgbWFpbj1zcHJpbnRmKCclczogT3J0aG9sb2dvdXMgY2F0ZWdvcmllcyAoQ09HcykgZm9yICVkXG4gY29tbW9uIHNlcXVlbmNlcyBhdCA5OCUlIHNzJywgbXljYXNlLCBucm93KG15YW5ub3QpKSwgY2V4PTAuNzUpCn0KYGBgCgoKCiMjIE9uIFRvcCBERVNlcSBkaWZmZXJlbnRpYWwgZXhwcmVzc2lvbiByZXN1bHRzLCA5OCUgc2VxdWVuY2Ugc2ltaWxhcml0eSBmZWF0dXJlcwoKRm9sbG93aW5nIHBsb3RzIGRlcGljdCBlbnp5bWUgYW5kIENPRyBhbm5vdGF0aW9uIGdyb3VwIG9uIERFIHJlc3VsdHMgb2YgOTglIHNzIGZlYXR1cmVzIHVwIHRvIGFkanVzdGVkIFMtdmFsdWUgJFxsZSQgMTBeLTReLCBmb3IgZWFjaCBjb250cmFzdC4KCmBgYHtyLCBmaWcuaGVpZ2h0PTYsIGZpZy53aWR0aD0xMH0KcHYudGhyID0gMWUtNApteWNhc2VzID0gYygnQ0Qtbm9uSUJEJywgJ1VDLW5vbklCRCcsICdIaWdoLUxvdycpCmZvcihteWNhc2UgaW4gbXljYXNlcykgewogIGlmKGdyZXBsKCdub25JQkQnLCBteWNhc2UpKSB7CiAgICByZXN1bHRGaWxlID0gcGFzdGUwKGRleHBEaXIwLCAnZGlhZ25vc2lzLScsIG15Y2FzZSwgJy1jZDk4LmNzdi5neicpCiAgfSBlbHNlIHsKICAgIHJlc3VsdEZpbGUgPSBwYXN0ZTAoZGV4cERpcjAsICdBY3Rpdml0eUxldmVsLScsIG15Y2FzZSwgJy1jZDk4LmNzdi5neicpCiAgfQogIAogIHJlc0RhdGEgPSBmcmVhZChmaWxlID0gcmVzdWx0RmlsZSkKICAKICBkZWRhdGEgPSByZXNEYXRhW3AuYWRqdXN0KGFwZS5zdmFsdWUsICdmZHInKSA8IHB2LnRociwgLihnZW5lX2lkLCBwYWRqLCBhcGUuc3ZhbHVlKV0KICAjIGZsb2cuaW5mbygnJXM6ICVkIGZlYXR1cmVzIHdpdGggcC1WYWx1ZSA8ICUuNWcnLCBteWNhc2UsIG5yb3coZGVkYXRhKSwgcHYudGhyKQogIG15YW5ub3QgPSBhbm5vdHNbZGVkYXRhLCBvbj0nbG9jdXNfdGFnPT1nZW5lX2lkJ10KICAKICAjIyMjIENvbXB1dGUgb3VyIHN1bW1hcmllcyAjIyMjCiAgIyBGaXJzdCBsZXZlbCBFQyBjYXRlZ29yaWVzCiAgZWMxbCA9IEVDJGdyb3Vwc1tzdWJzdWJjbGFzcz09MCAmIHN1YmNsYXNzPT0wLCAuKGNsYXNzLCBoZWFkaW5nLCBjb2xvcildCiAgc21yeS5FQyA9IGVjMWxbbXlhbm5vdFsgLCAuTiwgYnk9J0VDMSddLCBvbj0nY2xhc3M9PUVDMSddCiAgc2V0KHNtcnkuRUMsIGk9d2hpY2goaXMubmEoc21yeS5FQyRjbGFzcykpLCBqPWMoJ2hlYWRpbmcnLCdjb2xvcicpLCB2YWx1ZT1saXN0KCdOL0EnLCcjQUFBQUFBJykpCiAgc2V0a2V5KHNtcnkuRUMsIE4pCiAgIyBwbG90CiAgIyBwMSA9IHRyZWVtYXA6OnRyZWVtYXAoc21yeS5FQywgaW5kZXggPSAnaGVhZGluZycsIHZTaXplID0gJ04nLCAKICAjICAgICAgICAgICAgICAgICAgICAgICB0aXRsZT1zcHJpbnRmKCdFbnp5bWUgZ3JvdXAgb24gOTglJSBzcyBERSBmZWF0dXJlcyAoJWQgc2VxcyksICVzJywgbnJvdyhteWFubm90KSwgbXljYXNlKSkKICAKICBwaWUoeD1zbXJ5LkVDJE4sIGxhYmVscz1zbXJ5LkVDJGhlYWRpbmcsIGNvbD1zbXJ5LkVDJGNvbG9yLCBpbml0LmFuZ2xlID0gMTQwLCBjbG9ja3dpc2UgPSBGLCAKICAgICAgbWFpbj1zcHJpbnRmKCdFbnp5bWUgZ3JvdXAgb24gOTglJSBzcyBERSBmZWF0dXJlcyAoJWQgc2VxcyksICVzJywgbnJvdyhteWFubm90KSwgbXljYXNlKSkKICAKICAjIEZpcnN0IGNhdGVnb3J5IG9uIENPRwogIGFubi5jb2cxID0gQ09HJGNsdXN0ZXJzW215YW5ub3QsIC4oSUQ9bG9jdXNfdGFnLCBDYXRlZ29yeT1zdWJzdHIoY2F0ZWdvcmllcywxLDEpLCBjb2dOYW1lLCBjb2dJZCksIG9uPSdjb2dJZD09Q09HJ10KICBzbXJ5LmNvZyA9IENPRyRncm91cHNbYW5uLmNvZzFbICwgLk4sIGJ5PSdDYXRlZ29yeSddLCBvbj0nQ2F0ZWdvcnknXQogIHNldChzbXJ5LmNvZywgaT13aGljaChpcy5uYShzbXJ5LmNvZyRDYXRlZ29yeSkpLCBqPWMoJ0NhdGVnb3J5JywnRnVuY3Rpb24nLCdjb2xvcicpLCB2YWx1ZT1saXN0KCcnLCAnTi9BJywgJyNBQUFBQUEnKSkKICBzZXRrZXkoc21yeS5jb2csIE4pCiAgCiAgIyBNYWtlIHRoZSBwbG90cwogICMgcDIgPSB0cmVlbWFwOjp0cmVlbWFwKHNtcnkuY29nLCBpbmRleD0nQ2F0ZWdvcnknLCB2U2l6ZSA9ICdOJywgdkNvbG9yID0gJ2NvbG9yJywgdHlwZT0nY29sb3InLCAKICAjICAgICAgICAgICAgICAgICAgICAgICB0aXRsZT1zcHJpbnRmKCdPcnRob2xvZ291cyBjYXRlZ29yaWVzIG9uIDk4JSUgc3MgREUgZmVhdHVyZXMgKCVkIHNlcXMpLCAlcycsIG5yb3cobXlhbm5vdCksIG15Y2FzZSkpCiAgCiAgbGFicyA9IHNtcnkuY29nJEZ1bmN0aW9uCiAgaWYobGVuZ3RoKGxhYnMpID4gMTcpIHsKICAgIGxhYnNbMTo5XSA9ICcnCiAgICBsYWJzWzRdID0gJ090aGVyIGZ1bmN0aW9uYWwgZ3JvdXBzJwogIH0gZWxzZSBpZihsZW5ndGgobGFicykgPiAxMCkgewogICAgbGFic1sxOjRdID0gJycKICAgIGxhYnNbMl0gPSAnT3RoZXIgZnVuY3Rpb25hbCBncm91cHMnCiAgfQogIGxhYnMgPSBnc3ViKCdQb3N0dHJhbnNsYXRpb25hbCcsICdQVCcsIGxhYnMpCiAgcGllKHg9c21yeS5jb2ckTiwgbGFiZWxzPWxhYnMsIGNvbD1zbXJ5LmNvZyRjb2xvciwgaW5pdC5hbmdsZSA9IDE0MCwgY2xvY2t3aXNlID0gRiwKICAgICAgbWFpbj1zcHJpbnRmKCdPcnRob2xvZ291cyBjYXRlZ29yaWVzIG9uIDk4JSUgc3MgREUgZmVhdHVyZXMgKCVkIHNlcXMpLCAlcycsIG5yb3cobXlhbm5vdCksIG15Y2FzZSksIGNleD0wLjc1KQp9CmBgYAoKIyBQcm90ZWluIGNsdXN0ZXIgaGlzdG9ncmFtcwoKYGBge3J9CmNzdmFubm90ZmlsZSA9IHBhc3RlMChwcm9qRGlyLCAnZG9jLzIwMjAwNzA2LXNPUkYtQW5ub3RhdGlvbi9GdWxsQW5ub3RhdGlvbi1PUkYuY3N2Lmd6JykKCmZhbm5vdCA9IGZyZWFkKGZpbGUgPSBjc3Zhbm5vdGZpbGUpCmBgYAoKIyMgT3ZlciBhbGwgaWRlbnRpZmllZCBnZW5lcwoKIyMjIFVuaXF1ZSBnZW5lcyAtPiBVbmlxdWUgcHJvdGVpbnMKCkFsbCB1bmlxdWUgRE5BIHNlcXVlbmNlcywgZXhwcmVzc2VkIG9yIG5vdCwgY2x1c3RlcmVkIGF0IDEwMCUgYW1pbm8gYWNpZCBzZXF1ZW5jZSBzaW1pbGFyaXR5LiBFYWNoIGNsdXN0ZXIgaGVyZSBpcyBlc3NlbnRpYWxseSBhIHVuaXF1ZSBwcm90ZWluLgoKYGBge3IsIHdhcm5pbmc9RkFMU0UsIGZpZy5oZWlnaHQ9NiwgZmlnLndpZHRoPTEwfQojIEdldCB0aGUgdW5pcXVlIEROQSBzZXF1ZW5jZXMKdWRuYSA9IGZhbm5vdFssIC4oY2RfZG5hPXVuaXEuSUQubiwgY2QxMDA9dW5pcS5JRC5wLCBjZDk4KV0Kc3RvcGlmbm90KG5yb3codW5pcXVlKHVkbmEpKSA9PSB1bmlxdWVOKHVkbmFbWydjZF9kbmEnXV0pKQp1ZG5hID0gdW5pcXVlKHVkbmEpCmR1aWRhID0gdW5pcXVlKHVkbmFbLCAuKGNsdXNfc3o9Lk4pLCBieT0nY2QxMDAnXSkKCmdnID0gZ2dwbG90KGRhdGE9ZHVpZGEsIGFlcyh4PWNsdXNfc3opKSArIAogIGdlb21faGlzdG9ncmFtKGJpbnM9bWF4KGR1aWRhW1snY2x1c19zeiddXSksIGZpbGw9J2xpZ2h0Ymx1ZScsIGNvbG9yPSdkYXJrYmx1ZScsIGxpbmV3aWR0aD0wLjEpICsKICBzY2FsZV95X2NvbnRpbnVvdXModHJhbnM9J2xvZzEwJykgKwogIGFubm90YXRpb25fbG9ndGlja3Moc2lkZXM9J2wnKSArCiAgdGhlbWVfbGluZWRyYXcoKSArCiAgbGFicyh0aXRsZT0nTnVtYmVyIG9mIHVuaXF1ZSBjbHVzdGVycyB2cy4gY2x1c3RlciBzaXplJywgCiAgICAgICBzdWJ0aXRsZT0nQWxsIHVuaXF1ZSBETkEgc2VxdWVuY2VzIGNsdXN0ZXJlZCBhdCAxMDAlIEFBIHNzLicsCiAgICAgICB4PSdDbHVzdGVyIHNpemUnICkKZ2cKYGBgCgojIyMgVW5pcXVlIGdlbmVzIC0+IFVuaXF1ZSBwb3J0ZWluIGNsdXN0ZXJzIDk4JQoKQWxsIHVuaXF1ZSBETkEgc2VxdWVuY2VzICh3aGV0aGVyIGV4cHJlc3NlZCBvciBub3QpIGNsdXN0ZXJlZCBhdCA5OCUgYW1pbm8gYWNpZCBzZXF1ZW5jZSBzaW1pbGFyaXR5LgoKYGBge3IsIHdhcm5pbmc9RkFMU0UsIGZpZy5oZWlnaHQ9NiwgZmlnLndpZHRoPTEwfQpkdWlkYSA9IHVuaXF1ZSh1ZG5hWywgLihjbHVzX3N6PS5OKSwgYnk9J2NkOTgnXSkKCmdnID0gZ2dwbG90KGRhdGE9ZHVpZGEsIGFlcyh4PWNsdXNfc3opKSArIAogIGdlb21faGlzdG9ncmFtKGJpbnM9bWF4KGR1aWRhW1snY2x1c19zeiddXSksIGZpbGw9J2xpZ2h0Ymx1ZScsIGNvbG9yPSdkYXJrYmx1ZScsIGxpbmV3aWR0aD0wLjEpICsKICBzY2FsZV95X2NvbnRpbnVvdXModHJhbnM9J2xvZzEwJykgKwogIGFubm90YXRpb25fbG9ndGlja3Moc2lkZXM9J2wnKSArCiAgdGhlbWVfbGluZWRyYXcoKSArCiAgbGFicyh0aXRsZT0nTnVtYmVyIG9mIHVuaXF1ZSBjbHVzdGVycyB2cy4gY2x1c3RlciBzaXplJywgCiAgICAgICBzdWJ0aXRsZT0nQWxsIHVuaXF1ZSBETkEgc2VxdWVuY2VzIGNsdXN0ZXJlZCBhdCA5OCUgQUEgc3MuJywKICAgICAgIHg9J0NsdXN0ZXIgc2l6ZScgKQpnZwoKYGBgCgojIyMgVW5pcXVlIHByb3RlaW5zIC0+IFVuaXF1ZSBwcm90ZWluIGNsdXN0ZXJzIDk4JQoKYGBge3IsIHdhcm5pbmc9RkFMU0UsIGZpZy5oZWlnaHQ9NiwgZmlnLndpZHRoPTEwfQpzZXQodWRuYSwgaj0nY2RfZG5hJywgdmFsdWU9TlVMTCkKc3RvcGlmbm90KG5yb3codW5pcXVlKHVkbmEpKSA9PSB1bmlxdWVOKHVkbmFbWydjZDEwMCddXSkpCnVkbmEgPSB1bmlxdWUodWRuYSkKZHVpZGEgPSB1bmlxdWUodWRuYVssIC4oY2x1c19zej0uTiksIGJ5PSdjZDk4J10pCgpnZyA9IGdncGxvdChkYXRhPWR1aWRhLCBhZXMoeD1jbHVzX3N6KSkgKyAKICBnZW9tX2hpc3RvZ3JhbShiaW5zPW1heChkdWlkYVtbJ2NsdXNfc3onXV0pLCBmaWxsPScjOUJDRDlCJywgY29sb3I9J2RhcmtibHVlJywgbGluZXdpZHRoPTAuMSkgKwogIHNjYWxlX3lfY29udGludW91cyh0cmFucz0nbG9nMTAnKSArCiAgYW5ub3RhdGlvbl9sb2d0aWNrcyhzaWRlcz0nbCcpICsKICB0aGVtZV9saW5lZHJhdygpICsKICBsYWJzKHRpdGxlPSdOdW1iZXIgb2YgdW5pcXVlIGNsdXN0ZXJzIHZzLiBjbHVzdGVyIHNpemUnLCAKICAgICAgIHN1YnRpdGxlPSdVbmlxdWUgQUEgc2VxdWVuY2VzIGNsdXN0ZXJlZCBhdCA5OCUgQUEgc3MuJywKICAgICAgIHg9J0NsdXN0ZXIgc2l6ZScgKQpnZwpgYGAKCiMjIE92ZXIgZXhwcmVzc2VkIGdlbmVzCgpIaXN0b2dyYW1zIGFuZCBjbHVzdGVycyBhcmUgcmVzdHJpY3RlZCB0byB0aG9zZSBjbHVzdGVyIGlkZW50aWZpZXJzIGF0IDk4JSB0aGF0IHBhc3MgdGhlIGRpZmZlcmVudGlhbCBleHByZXNzaW9uIG1pbmltdW0gZXhwcmVzc2lvbiBjcml0ZXJpYSAobnVtYmVyIG9mIHJlYWRzIGluIHByb3BvcnRpb24gb2Ygc2FtcGxlcykuCgojIyMgVW5pcXVlIGdlbmVzIC0+IFVuaXF1ZSBwcm90ZWluIGNsdXN0ZXJzIDk4JQoKYGBge3J9Cm51Y3VpZHMgPSByb3dEYXRhKGRub3ZvOTgudnN0KVtbJ2NkOTgnXV0KdWRuYSA9IGZhbm5vdFtudWN1aWRzLCAuKGNkX2RuYT11bmlxLklELm4sIGNkMTAwPXVuaXEuSUQucCwgY2Q5OCksIG9uPSdjZDk4J10Kc3RvcGlmbm90KHVuaXF1ZU4odWRuYVtbJ2NkOTgnXV0pID09IHVuaXF1ZU4obnVjdWlkcykpCnVkbmEgPSB1bmlxdWUodWRuYSkKYGBgCgpgYGB7ciwgd2FybmluZz1GQUxTRSwgZmlnLmhlaWdodD02LCBmaWcud2lkdGg9MTB9CmR1aWRhID0gdW5pcXVlKHVkbmFbLCAuKGNsdXNfc3o9Lk4pLCBieT0nY2Q5OCddKQoKZ2cgPSBnZ3Bsb3QoZGF0YT1kdWlkYSwgYWVzKHg9Y2x1c19zeikpICsgCiAgZ2VvbV9oaXN0b2dyYW0oYmlucz1tYXgoZHVpZGFbWydjbHVzX3N6J11dKSwgZmlsbD0nY2FkZXRibHVlMicsIGNvbG9yPSdkb2RnZXJibHVlNCcsIGxpbmV3aWR0aD0wLjEpICsKICBzY2FsZV95X2NvbnRpbnVvdXModHJhbnM9J2xvZzEwJykgKwogIGFubm90YXRpb25fbG9ndGlja3Moc2lkZXM9J2wnKSArCiAgdGhlbWVfbGluZWRyYXcoKSArCiAgbGFicyh0aXRsZT0nTnVtYmVyIG9mIHVuaXF1ZSBjbHVzdGVycyB2cy4gY2x1c3RlciBzaXplLCBleHByZXNzZWQgZ2VuZXMnLCAKICAgICAgIHN1YnRpdGxlPSdBbGwgdW5pcXVlIEROQSBzZXF1ZW5jZXMgY2x1c3RlcmVkIGF0IDk4JSBBQSBzcy4nLAogICAgICAgeD0nQ2x1c3RlciBzaXplJyApCmdnCmBgYAoKIyBUYXhvbm9taWMgZG90cGxvdAoKYGBge3IsIGluY2x1ZGU9RkFMU0V9CiMgTG9hZCB0aGUgZnVsbCB0YXhvbm9taWMgdGFibGUgb2YgdGhlIHN1cGVya2luZG9tcyBpbiB0aGUgYW5hbHlzaXMKdGF4YXRibCA9IE5VTEwKdGF4ZG1wVGFyRmlsZSA9IHBhc3RlMChtZXRhRGlyLCAnbmV3X3RheGR1bXAudGFyLmd6JykKdGZsID0gdW50YXIodGFyZmlsZT10YXhkbXBUYXJGaWxlLCBsaXN0PVQpCm5uID0gZ3JlcCgncmFua2VkbGluZWFnZScsIHRmbCkKaWYobGVuZ3RoKG5uKSA9PSAxKSB7CiAgdW50YXIodGFyZmlsZT10YXhkbXBUYXJGaWxlLCBmaWxlcz10Zmxbbm5dLCBleGRpcj1wYXRoLmV4cGFuZChvdXREaXIpKQogIHRheGRtcEZpbGUgPSBwYXN0ZTAob3V0RGlyLCAncmFua2VkbGluZWFnZS5kbXAnKQogICMgV2UgYWxyZWFkeSBrbm93IGV2ZW4gY29sdW1ucyBhcmUgc2VwYXJhdG9ycwogIHRheGF0YmwgPSBmcmVhZChmaWxlPXRheGRtcEZpbGUsIGhlYWRlcj1GLCBkcm9wPXNlcSgyLDIwLDIpKQogIHNldG5hbWVzKHRheGF0YmwsIG5ldz1jKCd0YXhfaWQnLCd0YXhfbmFtZScsJ3NwZWNpZXMnLCdnZW51cycsJ2ZhbWlseScsJ29yZGVyJywnY2xhc3MnLCdwaHlsdW0nLCdraW5nZG9tJywnc3VwZXJraW5nZG9tJykpCiAgZmlsZS5yZW1vdmUodGF4ZG1wRmlsZSkKfQpgYGAKCgpgYGB7ciwgaW5jbHVkZT1GQUxTRX0KbmNiaXJlZnMgPSBOVUxMCm5jYmlSZWZGaWxlID0gcGFzdGUwKG1ldGFEaXIsICdOQ0JJLVJlZlNlcS1CYWN0ZXJpYS1hc3NlbWJseV9zdW1tYXJ5LnR4dC5neicpCm5jYmlyZWZzID0gZnJlYWQobmNiaVJlZkZpbGUsIHF1b3RlPScnKQpzZXRuYW1lcyhuY2JpcmVmcywgb2xkPScjIGFzc2VtYmx5X2FjY2Vzc2lvbicsIG5ldz0nZ2Vub21lJykKbmNiaXJlZnMgPSB1bmlxdWUobmNiaXJlZnNbLCAuKGdlbm9tZSwgdGF4aWQsIHNwZWNpZXNfdGF4aWQsIG9yZ2FuaXNtX25hbWUpXSkKCmdlbmVhbm5vdCA9IE5VTEwKZ2Fubm90RmlsZSA9IHBhc3RlMChwcm9qRGlyLCAnZGF0YS8yMDIwMDkyMS1zT1JGLXJlZmVyZW5jZS9zT1JGLXJlZmVyZW5jZS0xMDAuZ3RmLnJkcycpCmdlbmVhbm5vdCA9IHJlYWRSRFMoZ2Fubm90RmlsZSkKZ2Vub21lYW5ub3QgPSB1bmlxdWUoZ2VuZWFubm90WywgbmNiaV9nZW5vbWUsIGJ5PSdzZXFuYW1lJ10pCmBgYAoKCmBgYHtyfQpkby5hcGUgPSBUUlVFCnJlc2xpc3QgPSBOVUxMCnJlcyA9IE5VTEwKaW5kaXYgPSBOVUxMCmZvcihjb250cmFzdCBpbiBjKCdkaWFnbm9zaXMtQ0Qtbm9uSUJEJywnZGlhZ25vc2lzLVVDLW5vbklCRCcsJ0FjdGl2aXR5TGV2ZWwtSGlnaC1Mb3cnKSkgewogIGZvcihhZ2dyLmZsZCBpbiBjKCdwcm90X3VpZCcsJ2NkOTgnKSkgewogICAgc3N0eXBlID0gaWZlbHNlKGFnZ3IuZmxkPT0nY2Q5OCcsICc5OCUnLCAnMTAwJScpCiAgICAjIFJlYWQgdGhlIGRpZmZlcmVudGlhbCByZXN1bHRzIGluCiAgICBkZXhwUmVzRmlsZSA9IHBhc3RlMChkZXhwRGlyMCwgY29udHJhc3QsICctJywgYWdnci5mbGQsICcuY3N2Lmd6JykKICAgIHN0b3BpZm5vdChmaWxlLmV4aXN0cyhkZXhwUmVzRmlsZSkpCiAgICBhcmVzID0gZnJlYWQoZGV4cFJlc0ZpbGUsIGRyb3A9YygnU3RhcnQyJywnRW5kMicsJ1N0cmFuZDInLCdzZXEubnVjJywnc2VxLm51YzJ0Jywnc2VxLmFhJykpCiAgICAKICAgICMgc3RvcGlmbm90KGFsbChhcmVzJGdlbmVfaWQgJWluJSB1bmxpc3QoZ2VuZWluZm8kZ2VuZVssIC4uYWdnci5mbGRdKSkpCiAgICBmbG9nLmluZm8oJz09PSBSZXN1bHRzIGZvciAlcyAoJXMgU1MpIHdpdGggTEZDID4gJWQgYW5kIHAtdmFsdWUgPCAlZzonLCBjb250cmFzdCwgc3N0eXBlLCB0aHJlcy5sZmMsIHRocmVzLnB2KQogICAgZmxvZy5pbmZvKCcgIFN0ZDogJWQnLCBucm93KGFyZXNbcGFkaiA8PSB0aHJlcy5wdiAmIGFicyhsb2cyRkMpID49IHRocmVzLmxmYywgXSkpCiAgICBmbG9nLmluZm8oJyAgQVBFZ2xtOiAlZCcsIG5yb3coYXJlc1thcGUuc3ZhbHVlIDw9IHRocmVzLnB2ICYgYWJzKGFwZS5sb2cyRkMpID49IHRocmVzLmxmYywgXSkpCiAgICAKICAgIHsKICAgICAgIyBMaXN0IG9mIHNpZ25pZiBpZGVudGlmaWVycwogICAgICBpZihkby5hcGUpIHsKICAgICAgICBteUlkcyA9IGFyZXNbYXBlLnN2YWx1ZSA8PSB0aHJlcy5wdiAmIGFicyhhcGUubG9nMkZDKSA+PSB0aHJlcy5sZmMsIC4oZ2VuZV9pZCwgcHZhbD1hcGUuc3ZhbHVlLCBsb2cyRkM9YXBlLmxvZzJGQyldCiAgICAgIH0gZWxzZSB7CiAgICAgICAgbXlJZHMgPSBhcmVzW3BhZGogPD0gdGhyZXMucHYgJiBhYnMobG9nMkZDKSA+PSB0aHJlcy5sZmMsIC4oZ2VuZV9pZCwgcHZhbD1wYWRqLCBsb2cyRkMpXQogICAgICB9CiAgICAgICMgbXlJZHMgPSBnZW5laW5mbyRnZW5lW215SWRzLCBvbj1wYXN0ZTAoYWdnci5mbGQsICc9PWdlbmVfaWQnKV0KICAgICAgbXlJZHMgPSBmYW5ub3RbLCAuKHNlcWlkLCBzb3VyY2UsIHRheGRvbWFpbiwgSUQ9b3JpZy5JRCwgcHJvdF91aWQ9dW5pcS5JRC5wLCBjZDk4KV1bbXlJZHMsIG9uPXBhc3RlMChhZ2dyLmZsZCwgJz09Z2VuZV9pZCcpXQogICAgICBteUlkcyA9IG15SWRzWywgbiA6PSAuTiwgYnk9YWdnci5mbGRdICAgIyBOdW1iZXIgb2YgdW5pcXVlIGdlbmVzIHBlciBjbHVzdGVyCiAgICAgIGZsb2cuaW5mbygnICBVbmlxdWUgc2NhZmZvbGRzOiAlZCcsIHVuaXF1ZU4obXlJZHNbWydzZXFpZCddXSkpCiAgICAgIGZsb2cuaW5mbygnICBVbmlxdWUgZ2Vub21lczogJWQnLCB1bmlxdWVOKG15SWRzW1snc291cmNlJ11dKSkKICAgICAgZmxvZy5pbmZvKCcgIFVuaXF1ZSBDRFM6ICVkOyAlZCBhdCAlcyBTUycsIG5yb3cobXlJZHMpLCB1bmlxdWVOKG15SWRzW1thZ2dyLmZsZF1dKSwgc3N0eXBlKQogICAgICAKICAgICAgbXlJZHMgPSBuY2JpcmVmc1tteUlkcywgb249J2dlbm9tZT09c291cmNlJ10KICAgICAgZmxvZy5pbmZvKCcgIFVuaXF1ZSB0YXhhIElkOiAlZCcsIHVuaXF1ZU4obXlJZHNbWyd0YXhpZCddXSkpCiAgICAgIGZsb2cuaW5mbygnICBVbmlxdWUgc3BlY2llcyB0YXhhIElkOiAlZCcsIHVuaXF1ZU4obXlJZHNbWydzcGVjaWVzX3RheGlkJ11dKSkKICAgICAgCiAgICAgICMgQ29tcHV0ZSB0b3RhbCBudW1iZXIgb2YgY2x1c3RlcnMgcGFzc2luZyBkZXRlY3Rpb24gZmlsdGVycyBmb3IgREUgZm9yIHRheGEgaWQgaW4gc2lnbmlmaWNhbnQgcmVzdWx0cwogICAgICAjIFNjYWZmb2xkcyBmcm9tIHRheGEgaWQgaW4gcmVzdWx0CiAgICAgIGNwZGYgPSBnZW5vbWVhbm5vdFtuY2JpX2dlbm9tZSAlaW4lIHVuaXF1ZShteUlkcyRnZW5vbWUpLCBdCiAgICAgICMgR2V0IGFsbCBnZW5lcyBmcm9tIHRoZSBzY2FmZm9sZHMgd2l0aGluIHRoZSBERSBzaWduaWZpY2FudCByZXN1bHRzIChpbiBteUlkcykKICAgICAgY2RzZnR4ID0gZmFubm90W2NwZGYsIC4oc2VxaWQsIHNvdXJjZSwgSUQ9b3JpZy5JRCwgcHJvdF91aWQ9dW5pcS5JRC5wLCBjZDk4KSwgb249J3NlcWlkPT1zZXFuYW1lJ10KICAgICAgIyBSZXN0cmljdCB0byB0aG9zZSBpbiBERSBhbmFseXNpcyAodGhhdCBpcywgdGhhdCBwYXNzIGRldGVjdGlvbiBmaWx0ZXJzKQogICAgICBubiA9IHdoaWNoKGNkc2Z0eFtbYWdnci5mbGRdXSAlaW4lIGFyZXMkZ2VuZV9pZCkKICAgICAgbm4xID0gbnJvdyhjZHNmdHgpCiAgICAgIG5uMiA9IG5yb3coZmFubm90KQogICAgICBmbG9nLmluZm8oJ1RoZSBzY2FmZm9sZHMgcGlja2VkIHVwIGJ5IERFIGdlbmVzIGNvbXByaXNlICVkIC8gJWQgKCUuMmYpIHRvdGFsIGdlbmVzJywgbm4xLCBubjIsIG5uMSAvIG5uMikKICAgICAgbm4xID0gdW5pcXVlTihjZHNmdHhbWydwcm90X3VpZCddXSkKICAgICAgbm4yID0gdW5pcXVlTihmYW5ub3RbWyd1bmlxLklELnAnXV0pCiAgICAgIGZsb2cuaW5mbygnVGhpcyBpcyAlZCAvICVkICglLjJmKSB1bmlxdWUgQUEgc2VxdWVuY2VzJywgbm4xLCBubjIsIG5uMSAvIG5uMikKICAgICAgY2RzZnR4ID0gY2RzZnR4W25uLF0KICAgICAgZmxvZy5pbmZvKCdSZXN0cmljdGluZyB0byBnZW5lcyB0aGF0IHBhc3MgZXhwcmVzc2lvbiBkZXRlY3Rpb24gZmlsdGVycywgdGhpcyByZXByZXNlbnRzOicsCiAgICAgICAgICAgICAgICBzYXBwbHkobmFtZXMoY2RzZnR4KSwgZnVuY3Rpb24obikgdW5pcXVlTihjZHNmdHhbW25dXSkpLCBjYXB0dXJlPVQpCiAgICAgIGZsb2cuaW5mbygiV2hlcmU6CiAgICAgICAgICAgICAgICBzZXFpZDogICAgc2NhZmZvbGQKICAgICAgICAgICAgICAgIHNvdXJjZTogICBOQ0JJIGdlbm9tZQogICAgICAgICAgICAgICAgSUQ6ICAgICAgIFByb2trYSBnZW5lCiAgICAgICAgICAgICAgICBwcm90X3VpZDogVW5pcXVlIEFBIHNlcSAoY2QxMDApCiAgICAgICAgICAgICAgICBjZDk4OiAgICAgVW5pcXVlIGNkOTggY2x1c3RlcgogICAgICAgICAgICAgICAgXG4iKQogICAgICAjIENvbXB1dGUgc3VtbWFyaWVzCiAgICAgIGNkc2Z0eCA9IGNkc2Z0eFssIC4odHgubm9yZz0uTiwgdHgubmFnZz11bmlxdWVOKC5TRCkpLCAuU0Rjb2xzPWFnZ3IuZmxkLCBieT0nc291cmNlJ10KICAgICAgIyBOb3cgYW5ub3RhdGUgb3VyIGxpc3QKICAgICAgbXlJZHMgPSBjZHNmdHhbbXlJZHMsIG9uPSdzb3VyY2U9PWdlbm9tZSddCiAgICAgIAogICAgICBteUlkc1sgLCBtIDo9IHN1bShuKSwgYnk9J3RheGlkJ10gICAgICAgIyBudW1iZXIgb2YgZ2VuZXMgaW4gcmVzdWx0IHBlciBnZW5vbWUgKHN0cmFpbikKICAgICAgIyByYXRpbyBvZiBjbHVzdGVycyBpbiBERSByZXN1bHRzIHRvIGNsdXN0ZXJzIHBhc3NpbmcgZGV0ZWN0aW9uCiAgICAgIG15SWRzWyAsIHByb3AuZGUgOj0gc3VtKG4pIC8gdHgubmFnZywgYnk9J3RheGlkJ10KICAgICAgCiAgICAgICMgQXMgd2Ugd2lsbCBmb2N1cyBvbiBzcGVjaWVzIChub3Qgc3RyYWlucyksIGNyZWF0ZSBzdW1tYXJpZXMgYnkgc3BlY2llcy4KICAgICAgIyBXZSBjYW4gdXNlIGF2ZXJhZ2Ugb2YgbnVtYmVyIG9mIENEUyBvciBjbHVzdGVycyBmb3IgYWxsIHN0cmFpbnMgb2Ygc3BlY2llcywgb3Igd2UgY291bGQgdXNlIG1pbmltdW0sIGFzIHdlIGFyZSBwcm9iYWJseSBvdmVyZXN0aW1hdGluZwogICAgICAjIG15SWRzWyAsIG1tIDo9IHJvdW5kKG1lYW4odW5pcXVlKG0pKSksIGJ5PSdzcGVjaWVzX3RheGlkJ10KICAgICAgIyBteUlkc1sgLCBzeC5ub3JnIDo9IG1pbih0eC5ub3JnKSwgYnk9J3NwZWNpZXNfdGF4aWQnXQogICAgICAjIG15SWRzWyAsIHN4Lm5hZ2cgOj0gbWluKHR4Lm5hZ2cpLCBieT0nc3BlY2llc190YXhpZCddCiAgICAgICMgbXlJZHNbICwgc3gubW9yZyA6PSByb3VuZChtZWFuKHVuaXF1ZSh0eC5ub3JnKSkpLCBieT0nc3BlY2llc190YXhpZCddCiAgICAgICMgbXlJZHNbICwgc3gubWFnZyA6PSByb3VuZChtZWFuKHVuaXF1ZSh0eC5uYWdnKSkpLCBieT0nc3BlY2llc190YXhpZCddCiAgICAgIAogICAgICAjIFNldHRsZSBmb3IgdGhlIHJhdGlvIG9mIG1lYW4gbnVtYmVyIG9mIGNsdXN0ZXJzIGluIERFIHJlc3VsdHMgb3ZlciB0aGUgbWVhbiBudW1iZXIgb2YgY2x1c3RlcnMgKHBhc3NpbmcgZGV0ZWN0aW9uKSBmb3IgZ2Vub21lcyBvZiB0aGUgc3BlY2llcwogICAgICAjIG15SWRzWyAsIHByb3AuZGUgOj0gbW0gLyBzeC5tYWdnXQoKICAgICAgIyBBbm5vdGF0ZSBzcGVjaWVzIGxldmVsICAgICAgCiAgICAgIG15SWRzID0gdGF4YXRibFtteUlkcywgb249J3RheF9pZD09c3BlY2llc190YXhpZCddCiAgICAgICMgUmVtb3ZlIHNvbWUgdW5uZWVkZWQKICAgICAgc2V0KG15SWRzLCBqPWMoJ3NvdXJjZScsJ3NwZWNpZXMnLCdraW5nZG9tJywnc3VwZXJraW5nZG9tJyksIHZhbHVlPWxpc3QocmVwKE5VTEwsNCkpKQoKICAgICAgIyBQZW5hbGlzZSBwLXZhbHVlcyBieSB0aGUgbnVtYmVyIG9mIGNsdXN0ZXJzIG9mIHRheGEgcGFzc2luZyBmaWx0ZXJzIChvciBieSBudW1iZXIgb2YgY2x1c3RlcnMgaW4gREUgcmVlc3VsdCA/KS4gRmlyc3QgY2xhbXAgdG9vIHNtYWxsIHB2YWx1ZXMKICAgICAgbXlJZHNbcHZhbCA8IDFlLTI0LCBwdmFsIDo9IDFlLTI0XQogICAgICBteUlkc1sgLCBhcHYgOj0gc2FwcGx5KHB2YWwgKiB0eC5uYWdnLCBmdW5jdGlvbih6KSBtaW4oMSwgeikpXQogICAgICAKICAgICAgIyBBZ2dyZWdhdGVkIHB2YWx1ZSBieSB0YXhhCiAgICAgIHN1cHByZXNzV2FybmluZ3MoewogICAgICAgIHR4cyA9IHVuaXF1ZShteUlkc1sgLCAuKHRheF9pZCwgdGF4X25hbWUsIGdlbnVzLCBmYW1pbHksIHBoeWx1bSwgb3JnYW5pc21fbmFtZSwgbT1tWzFdLCBwcm9wLmRlPXByb3AuZGVbMV0sIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1pbi5wPW1ldGFwOjptaW5pbXVtcChhcHYsIGxvZy5wPVQpJHAsIGFwdj1sb2cobWluKGFwdikpKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBieT0ndGF4aWQnXSkKICAgICAgfSkKICAgICAgdHhzW2lzLm5hKG1pbi5wKSwgbWluLnAgOj0gYXB2XQogICAgICAKICAgICAgIyBTdW1tYXJpc2UgYnkgc3BlY2llcwogICAgICBzcHMgPSB1bmlxdWUodHhzWyAsIC4odGF4X25hbWUsIGdlbnVzLCBmYW1pbHksIHBoeWx1bSwgbT1yb3VuZChtZWFuKG0pKSwgcHJvcC5kZT1tYXgocHJvcC5kZSksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgcGRlPW1lYW4ocHJvcC5kZSksIG1pbi5wPW1lYW4obWluLnApKSwgCiAgICAgICAgICAgICAgICAgICAgICAgIGJ5PSd0YXhfaWQnXSkKCiAgICAgICMgU29tZSBjbGVhbnVwCiAgICAgICMgc2V0bmFtZXMobXlJZHMsIG9sZD1jKCd0YXhfaWQnLCd0YXhfbmFtZScpLCBuZXc9YygnU3BlY2llcyBUYXhJZCcsJ1NwZWNpZXMgTmFtZScpKQogICAgICAKICAgICAgYWNvbnQgPSBnc3ViKCdkaWFnbm9zaXMtJywgJycsIGNvbnRyYXN0LCBmaXhlZD1UKQogICAgICBhY29udCA9IGdzdWIoJ0FjdGl2aXR5TGV2ZWwtJywgJ0FjdC4gJywgYWNvbnQsIGZpeGVkPVQpCiAgICAgIGFjb250ID0gZ3N1YignLScsICcgLSAnLCBhY29udCwgZml4ZWQ9VCkKICAgICAgYWNvbnQgPSBzcHJpbnRmKCclcyAoJXMgU1MpJywgYWNvbnQsIHNzdHlwZSkKICAgICAgdHhzWywgY29udCA6PSBhY29udF0KICAgICAgdHhzWywgc3N0eXBlIDo9IHNzdHlwZV0KICAgICAgc3BzWywgY29udCA6PSBhY29udF0KICAgICAgc3BzWywgc3N0eXBlIDo9IHNzdHlwZV0KICAgICAgbXlJZHNbLCBjb250IDo9IGFjb250XQogICAgICBteUlkc1ssIHNzdHlwZSA6PSBzc3R5cGVdCiAgICAgIAogICAgICByZXMgPSByYmluZChyZXMsIHNwcykKICAgICAgaW5kaXYgPSByYmluZChpbmRpdiwgbXlJZHMpCiAgICB9CiAgfQp9CmBgYApgYGB7cn0KZmxvZy5pbmZvKCdBY2Nyb3NzIGFsbCAzIERFIGNvbnRyYXN0cyAoQ0QgLSBub25JQkQsIFVDIC0gbm9uSUJELCBBY3Rpdml0eSBIaWdoIC0gTG93KSBhbmQgMiBjbHVzdGVyaW5nIHN0cmF0ZWdpZXMgKDEwMCUsIDk4JSkgd2UgaGF2ZSBpbiB0b3RhbDonKQpmbG9nLmluZm8oJyAgICAlZCB0YXhhICglZCB1bmlxdWUpLCBkaXN0cmlidXRlZCBhczonLCBucm93KHJlcyksIHVuaXF1ZU4ocmVzW1sndGF4X25hbWUnXV0pKQpmbG9nLmluZm8oJycsIHRhYmxlKHJlc1tbJ2NvbnQnXV0pLCBjYXB0dXJlPVRSVUUpCmZsb2cuaW5mbygnICAgICVkIGluZGl2aWR1YWwgZ2VuZSByZXN1bHRzICglZCB1bmlxdWUpJywgbnJvdyhpbmRpdiksIHVuaXF1ZU4oaW5kaXZbWydJRCddXSkpCmBgYAoKYGBge3J9CiMgbm4gPSB3aGljaChteXRheGFbWydpbl90cmVlJ11dKQojIG15dHJlZSA9IHJvdGw6OnRvbF9pbmR1Y2VkX3N1YnRyZWUob3R0X2lkcz1yb3RsOjpvdHRfaWQobXl0YXhhKVtubl0sIGxhYmVsX2Zvcm1hdD0nbmFtZScpCm10eCA9IHVuaXF1ZShyZXNbLCAuKHBoeWx1bSwgZmFtaWx5LCBnZW51cywgdGF4X25hbWUsIG1wdj1taW4obWluLnApKSwgYnk9J3RheF9pZCddKQpzZXRvcmRlcnYobXR4LCBjb2xzPWMoJ3BoeWx1bScsICdmYW1pbHknLCAnZ2VudXMnLCAnbXB2JykpCm10eGNvbCA9IGxpc3QoKSAgICMgQ29sb3JzCmNlbGxjb2xvcnMgPSBSQ29sb3JCcmV3ZXI6OmJyZXdlci5wYWwoOSwgJ1Bhc3RlbDEnKQojIEFmdGVyIHNvcnRpbmcsIGxlYXZlIG9ubHkgb25lIGNlbGwgd2l0aCBuYW1lIGluIGNvbHVtbiB1bnRpbCBuZXcgbmFtZS4gIFNvcnRpbmcgcGxhY2VzIGVtcHR5IGNlbGxzIGZpcnN0Lgpmb3IgKGogaW4gYygncGh5bHVtJywgJ2ZhbWlseScsICdnZW51cycpKSB7CiAgaWMgPSAwCiAgaWYgKGogPT0gJ3BoeWx1bScpIHsKICAgIG10eGNvbFtbal1dID0gcmVwKGNlbGxjb2xvcnNbMV0sIG5yb3cobXR4KSkgICMgVG8gYmUgb3ZlcndyaXR0ZW4KICB9IGVsc2UgaWYgKGogPT0gJ2ZhbWlseScpIHsKICAgIG10eGNvbFtbal1dID0gbXR4Y29sW1sncGh5bHVtJ11dCiAgfSBlbHNlIGlmIChqID09ICdnZW51cycpIHsKICAgIG10eGNvbFtbal1dID0gbXR4Y29sW1snZmFtaWx5J11dCiAgfQogIGZvciAoayBpbiB1bmlxdWUobXR4W1tqXV0pKSB7CiAgICBpZiAoayA9PSAnJykgbmV4dAogICAgaWMgPSBpYyArIDEKICAgIG5uID0gd2hpY2gobXR4W1tqXV0gPT0gaykKICAgICNmbG9nLmluZm8oJ0NvbHVtbiAlcywgdmFsdWUgIiVzIiAoJWQgaW5kaWNlcyksIGNvbG9yICVkOiVzJywgaiwgaywgbGVuZ3RoKG5uKSwgaWMsIGNlbGxjb2xvcnNbaWNdKQogICAgI2Zsb2cuaW5mbygnICBpOiAlcycsIHRvU3RyaW5nKG5uKSkKICAgIG10eGNvbFtbal1dW25uXSA9IGNlbGxjb2xvcnNbaWMgJSUgOSArIDFdCiAgICBubiA9IG5uWy0xXQogICAgaWYobGVuZ3RoKG5uKSA9PSAwKSBuZXh0CiAgICBtdHhbW2pdXVtubl0gPSAnJwogIH0KICAjZmxvZy5pbmZvKCcnLCBtdHhjb2xbW2pdXSwgY2FwdHVyZT1UKQp9CmBgYAoKCmBgYHtyfQojIEF0dGVtcHQgd2l0aCBjb21iaW5hdGlvbiBvZiBncmlkRXh0cmEgYW5kIGdncHVicgpteXRoZW1lID0gZ3JpZEV4dHJhOjp0dGhlbWVfbWluaW1hbChiYXNlX3NpemU9OSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvcmU9bGlzdChiZ19wYXJhbXM9bGlzdChmaWxsPW10eGNvbFtbJ3BoeWx1bSddXSwgY29sPU5BLCBhbHBoYT0wLjYpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmdfcGFyYW1zPWxpc3QoaGp1c3Q9MCwgeD0wLjAxKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhZGRpbmc9dW5pdChjKDIsIDIpLCAncHQnKSkKZ2cgPSBncmlkRXh0cmE6OnRhYmxlR3JvYihtdHhbLCAuKHBoeWx1bSwgZmFtaWx5LCBnZW51cywgdGF4X25hbWUpXSwgcm93cz1OVUxMLCBjb2xzPU5VTEwsIHRoZW1lPW15dGhlbWUpCmZvciAoayBpbiBzZXFfbGVuKG5yb3cobXR4KSkpIHsKICBnZyA9IGdnICU+JSAKICAgICAgICMgZ2dwdWJyOjp0YWJsZV9jZWxsX2JnKHJvdz1rLCBjb2x1bW49MSwgZmlsbD1tdHhjb2xbWydwaHlsdW0nXV1ba10sIGNvbD1OQSwgbGluZXdpZHRoPTApICU+JQogICAgICAgZ2dwdWJyOjp0YWJsZV9jZWxsX2JnKHJvdz1rLCBjb2x1bW49MiwgZmlsbD1tdHhjb2xbWydmYW1pbHknXV1ba10sIGNvbD1OQSwgbGluZXdpZHRoPTApICU+JQogICAgICAgZ2dwdWJyOjp0YWJsZV9jZWxsX2JnKHJvdz1rLCBjb2x1bW49MywgZmlsbD1tdHhjb2xbWydnZW51cyddXVtrXSwgY29sPU5BLCBsaW5ld2lkdGg9MCkKfQpmb3IgKGogaW4gYyhtdHhbcGh5bHVtICE9ICcnLCB3aGljaD1UUlVFXSkpIHsKICBnZyA9IGdnICU+JSBnZ3B1YnI6OnRhYl9hZGRfaGxpbmUoYXQucm93PWosIHJvdy5zaWRlPSd0b3AnLCBsaW5lY29sb3I9J2JsdWUnKQp9CmdnID0gZ2cgJT4lIGdncHVicjo6dGFiX2FkZF9obGluZShhdC5yb3c9bnJvdyhtdHgpLCByb3cuc2lkZT0nYm90dG9tJywgbGluZWNvbG9yPSdibHVlJykKCiMgTWFrZSB0YWJsZSBncm9iICJlbGFzdGljOgpubHcgPSBzdW0oY29sTWF4cyhhcy5tYXRyaXgobXR4WywgLihuY2hhcihwaHlsdW0pLCBuY2hhcihmYW1pbHkpLCBuY2hhcihnZW51cyksIG5jaGFyKHRheF9uYW1lKSldKSkpCmdnJGhlaWdodHMgPSB1bml0KHJlcCgxL25yb3coZ2cpLCBucm93KGdnKSksICducGMnKQojIGdnJHdpZHRocyA9IGdyaWQ6OnVuaXQucG1heChnZyR3aWR0aHMsIHVuaXQobmx3LCAnbGluZXMnKSkKCmRkID0gZGNhc3QocmVzLCB0YXhfaWQgKyBwaHlsdW0gKyBmYW1pbHkgKyBnZW51cyArIHRheF9uYW1lIH4gY29udCwgdmFsdWUudmFyPSdtaW4ucCcpCm5uID0gbWF0Y2gobXR4W1sndGF4X2lkJ11dLCBkZFtbJ3RheF9pZCddXSkgICMgU2FtZSBvcmRlciBhcyBzaWRlIHRhYmxlCmRkID0gZGRbbm4sIF0Kcm4gPSBkZCR0YXhfbmFtZQojIENoYW5nZSBzaWduIGFuZCBjb252ZXJ0IHRvIGxvZzEwCmRkID0gcm91bmQoLWFzLm1hdHJpeChkZFssIDY6bmNvbChkZCldKSpsb2cxMChleHAoMSkpLCBkaWdpdHM9MikKIyBkZFtkZCA+IDQwXSA9IDQwCnJvd25hbWVzKGRkKSA9IE5VTEwKCnBwID0gZGNhc3QocmVzLCB0YXhfaWQgKyBwaHlsdW0gKyBmYW1pbHkgKyBnZW51cyArIHRheF9uYW1lIH4gY29udCwgdmFsdWUudmFyPSdwcm9wLmRlJykKbm4gPSBtYXRjaChtdHhbWyd0YXhfaWQnXV0sIHBwW1sndGF4X2lkJ11dKSAgIyBTYW1lIG9yZGVyIGFzIHNpZGUgdGFibGUKcHAgPSBwcFtubiwgXQpwcCA9IHJvdW5kKGFzLm1hdHJpeChzcXJ0KDEwMCAqIHBwWywgNjpuY29sKHBwKV0pKSkKIyBwcFt3aGljaChwcCA+IDQpXSA9IDQKcm93bmFtZXMocHApID0gTlVMTAoKcXEgPSBhcy5kYXRhLmZyYW1lKHVuaXF1ZShyZXNbLCAuKHRheF9uYW1lLCBnZW51cywgcGh5bHVtKV0pW21hdGNoKHJuLCB0YXhfbmFtZSksIDI6M10sIHN0cmluZ3NBc0ZhY3RvcnM9VCkKcm93bmFtZXMocXEpID0gcm4KCnAxID0gaGVhdG1hcGx5OjpoZWF0bWFwbHkoZGQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgZGVuZHJvZ3JhbT0nbm9uZScsIG5hLnJtPVQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgZ3JpZF9jb2xvcj0nd2hpdGUnLCBncmlkX3dpZHRoPS4wMDAxLCBncmlkX3NpemU9MSwKICAgICAgICAgICAgICAgICAgICAgICAgICBmb250c2l6ZV9yb3c9OCwKICAgICAgICAgICAgICAgICAgICAgICAgICBmb250c2l6ZV9jb2w9OCwKICAgICAgICAgICAgICAgICAgICAgICAgICAjIGNlbGxub3RlX3NpemU9MTAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgbmEudmFsdWU9J2dyZXk1MCcsIAogICAgICAgICAgICAgICAgICAgICAgICAgIG1haW49c3ByaW50ZignRGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkIENEUyBhYnVuZGFuY2VcbmJ5IFNwZWNpZXMsICVzIFNTJywgc3N0eXBlKSwKICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbF9uYW1lcz1jKCdTcGVjaWVzJywnQ29udHJhc3QnLCctbG9nMTAocFYpJyksCiAgICAgICAgICAgICAgICAgICAgICAgICAgUm93dj1GQUxTRSwKICAgICAgICAgICAgICAgICAgICAgICAgICBDb2x2PUZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGVfdHlwZT0nc2NhdHRlcicsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIyBwbG90X21ldGhvZD0ncGxvdGx5JywKICAgICAgICAgICAgICAgICAgICAgICAgICBwbG90X21ldGhvZD0nZ2dwbG90JywKICAgICAgICAgICAgICAgICAgICAgICAgICAjIHJvd19zaWRlX2NvbG9ycz1xcSwKICAgICAgICAgICAgICAgICAgICAgICAgICBwb2ludF9zaXplX21hdD1wcCwKICAgICAgICAgICAgICAgICAgICAgICAgICBwb2ludF9zaXplX25hbWU9J0RFICVcbmV4cHJlc3NlZCcsCiAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuX3BweHB5PVRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIyBtYXJnaW5zPWMoNTAsIDUwLCBOQSwgMCksICAKICAgICAgICAgICAgICAgICAgICAgICAgICAjIGhpZGVfY29sb3JiYXI9VCwKICAgICAgICAgICAgICAgICAgICAgICAgICBoZWF0bWFwX2xheWVycz1saXN0KHRoZW1lKGF4aXMudGV4dC54PWVsZW1lbnRfdGV4dChhbmdsZT0tMzUsIGhqdXN0PTAsIHZqdXN0PTEpKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIGxlZ2VuZC50aXRsZT1lbGVtZW50X3RleHQoc2l6ZT04LCBjb2xvcj0nZGFya2JsdWUnKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgICAgICAgICAgICAgICAgICAgICAgICAgIGxlZ2VuZC50ZXh0PWVsZW1lbnRfdGV4dChzaXplPTgpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIyAgICAgICAgICAgICAgICAgICAgICAgICAgbGVnZW5kLmJveD0naG9yaXpvbnRhbCcsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAjICAgICAgICAgICAgICAgICAgICAgICAgICBsZWdlbmQua2V5LnNpemU9dW5pdCguMywgJ2NtJyksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAjICAgICAgICAgICAgICAgICAgICAgICAgICBsZWdlbmQuc3BhY2luZz11bml0KC4wMSwnY20nKSkpLAogICAgICAgICAgICAgICAgICAgICAgICAgICMgc2lkZV9jb2xvcl9sYXllcnM9bGlzdCh0aGVtZShsZWdlbmQudGl0bGU9ZWxlbWVudF90ZXh0KHNpemU9OCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxlZ2VuZC5rZXkuc2l6ZT11bml0KC4yLCdjbScpLAogICAgICAgICAgICAgICAgICAgICAgICAgICMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZWdlbmQuc3BhY2luZz11bml0KC4wNSwnY20nKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAjICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGVnZW5kLmJveD0naG9yaXpvbnRhbCcpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAjY29sb3JiYXJfeXBvcz0tMiwKICAgICAgICAgICAgICAgICAgICAgICAgICAjY29sb3JiYXJfeHBvcz0xLAogICAgICAgICAgICAgICAgICAgICAgICAgICNjb2xvcmJhcl94YW5jaG9yPSdsZWZ0JywKICAgICAgICAgICAgICAgICAgICAgICAgICAjY29sb3JiYXJfbGVuPTAuMSwgICAjIHBsb3RseQogICAgICAgICAgICAgICAgICAgICAgICAgICNjb2xvcmJhcl90aGlja25lc3M9MjAsICMgcGxvdGx5CiAgICAgICAgICAgICAgICAgICAgICAgICAgIyBzdWJwbG90X3dpZHRocz1jKDAuNiwwLjEpLAogICAgICAgICAgICAgICAgICAgICAgICAgIHNob3d0aWNrbGFiZWxzPWMoVFJVRSwgRkFMU0UpLAogICAgICAgICAgICAgICAgICAgICAgICAgIGxhYkNvbD1jb2xuYW1lcyhkZCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgIyBsYWJSb3c9cm93bmFtZXMoZGQpCiAgICAgICAgICAgICAgICAgICAgICAgICAgKQoKZ3AxID0gZ2dwbG90R3JvYihwMSRwKQpwYW5lbF9pZCA9IGdwMSRsYXlvdXRbZ3AxJGxheW91dCRuYW1lID09ICdwYW5lbCcsIGMoJ3QnLCAnbCcpXQpncDEgPSBndGFibGU6Omd0YWJsZV9hZGRfY29scyhncDEsIHVuaXQoMywgJ251bGwnKSwgcG9zPTApCmdwMSA9IGd0YWJsZTo6Z3RhYmxlX2FkZF9ncm9iKGdwMSwgZ3JvYnM9Z2csIHQ9cGFuZWxfaWQkdCwgbD0xLCBjbGlwPSdvbicsIHo9LUluZikKCiMgZ3JpZDo6Z3JpZC5kcmF3KGdwMSkKZ3ggPSBnZ3B1YnI6OmFzX2dncGxvdChncDEpCmBgYAoKCmBgYHtyLCBmaWcuaGVpZ2h0PTE1LCBmaWcud2lkdGg9OS41LCB3YXJuaW5nPUZBTFNFfQpwbG90KGd4KQpgYGAKCg==